Skip to content
GitLab
Explore
Projects
Groups
Snippets
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
iOSThirdRepo
ReactiveCocoa
Commits
aa8ba8c8
Commit
aa8ba8c8
authored
11 years ago
by
Justin Spahr-Summers
Browse files
Options
Download
Plain Diff
Merge pull request #1058 from ReactiveCocoa/signal-selector-class
Signal selector class
parents
e63f9d59
b822f885
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
ReactiveCocoaFramework/ReactiveCocoa/NSObject+RACSelectorSignal.m
+45
-0
...CocoaFramework/ReactiveCocoa/NSObject+RACSelectorSignal.m
ReactiveCocoaFramework/ReactiveCocoaTests/NSObjectRACSelectorSignalSpec.m
+27
-0
...mework/ReactiveCocoaTests/NSObjectRACSelectorSignalSpec.m
with
72 additions
and
0 deletions
+72
-0
ReactiveCocoaFramework/ReactiveCocoa/NSObject+RACSelectorSignal.m
+
45
-
0
View file @
aa8ba8c8
...
...
@@ -116,6 +116,42 @@ static void RACSwizzleRespondsToSelector(Class class) {
class_replaceMethod
(
class
,
respondsToSelectorSEL
,
imp_implementationWithBlock
(
newRespondsToSelector
),
method_getTypeEncoding
(
respondsToSelectorMethod
));
}
static
void
RACSwizzleGetClass
(
Class
class
,
Class
statedClass
)
{
SEL
selector
=
@selector
(
class
);
Method
method
=
class_getInstanceMethod
(
class
,
selector
);
IMP
newIMP
=
imp_implementationWithBlock
(
^
(
id
self
)
{
return
statedClass
;
});
class_replaceMethod
(
class
,
selector
,
newIMP
,
method_getTypeEncoding
(
method
));
}
static
void
RACSwizzleMethodSignatureForSelector
(
Class
class
)
{
SEL
selector
=
@selector
(
methodSignatureForSelector
:
);
Method
methodSignatureForSelectorMethod
=
class_getInstanceMethod
(
class
,
selector
);
IMP
newIMP
=
imp_implementationWithBlock
(
^
(
id
self
,
SEL
selector
)
{
// Don't send the -class message to the receiver because we've changed
// that to return the original class.
Class
actualClass
=
object_getClass
(
self
);
Method
method
=
class_getInstanceMethod
(
actualClass
,
selector
);
if
(
method
==
NULL
)
{
// Messages that the original class dynamically implements fall
// here.
//
// Call the original class' -methodSignatureForSelector:.
struct
objc_super
target
=
{
.
super_class
=
class_getSuperclass
(
actualClass
),
.
receiver
=
self
,
};
NSMethodSignature
*
(
*
messageSend
)(
struct
objc_super
*
,
SEL
)
=
(
__typeof__
(
messageSend
))
objc_msgSendSuper
;
return
messageSend
(
&
target
,
@selector
(
methodSignatureForSelector
:
));
}
char
const
*
encoding
=
method_getTypeEncoding
(
method
);
return
[
NSMethodSignature
signatureWithObjCTypes
:
encoding
];
});
class_replaceMethod
(
class
,
selector
,
newIMP
,
method_getTypeEncoding
(
methodSignatureForSelectorMethod
));
}
// It's hard to tell which struct return types use _objc_msgForward, and
// which use _objc_msgForward_stret instead, so just exclude all struct, array,
// union, complex and vector return types.
...
...
@@ -237,6 +273,9 @@ static Class RACSwizzleClass(NSObject *self) {
if
(
!
[
swizzledClasses
()
containsObject
:
className
])
{
RACSwizzleForwardInvocation
(
baseClass
);
RACSwizzleRespondsToSelector
(
baseClass
);
RACSwizzleGetClass
(
baseClass
,
statedClass
);
RACSwizzleGetClass
(
object_getClass
(
baseClass
),
statedClass
);
RACSwizzleMethodSignatureForSelector
(
baseClass
);
[
swizzledClasses
()
addObject
:
className
];
}
}
...
...
@@ -253,6 +292,12 @@ static Class RACSwizzleClass(NSObject *self) {
RACSwizzleForwardInvocation
(
subclass
);
RACSwizzleRespondsToSelector
(
subclass
);
RACSwizzleGetClass
(
subclass
,
statedClass
);
RACSwizzleGetClass
(
object_getClass
(
subclass
),
statedClass
);
RACSwizzleMethodSignatureForSelector
(
subclass
);
objc_registerClassPair
(
subclass
);
}
...
...
This diff is collapsed.
Click to expand it.
ReactiveCocoaFramework/ReactiveCocoaTests/NSObjectRACSelectorSignalSpec.m
+
27
-
0
View file @
aa8ba8c8
...
...
@@ -384,4 +384,31 @@ describe(@"-rac_signalForSelector:fromProtocol", ^{
});
});
describe
(
@"class reporting"
,
^
{
__block
RACTestObject
*
object
;
__block
Class
originalClass
;
beforeEach
(
^
{
object
=
[[
RACTestObject
alloc
]
init
];
originalClass
=
object
.
class
;
});
it
(
@"should report the original class"
,
^
{
[
object
rac_signalForSelector
:
@selector
(
lifeIsGood
:)];
expect
(
object
.
class
).
to
.
beIdenticalTo
(
originalClass
);
});
it
(
@"should report the original class when it's KVO'd after dynamically subclassing"
,
^
{
[
object
rac_signalForSelector
:
@selector
(
lifeIsGood
:)];
RACObserve
(
object
,
objectValue
);
expect
(
object
.
class
).
to
.
beIdenticalTo
(
originalClass
);
});
it
(
@"should report the original class when it's KVO'd before dynamically subclassing"
,
^
{
RACObserve
(
object
,
objectValue
);
[
object
rac_signalForSelector
:
@selector
(
lifeIsGood
:)];
expect
(
object
.
class
).
to
.
beIdenticalTo
(
originalClass
);
});
});
SpecEnd
This diff is collapsed.
Click to expand it.
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment
Menu
Explore
Projects
Groups
Snippets