, . ( ), . , .
, performSelector:, . , "Undeclared Selector" (GCC_WARN_UNDECLARED_SELECTOR), .
, . , , , . , , . ( , , , ).
#import <objc/runtime.h>
@interface RNDelegateTrampoline : NSObject {
@private
id delegate_;
Protocol *protocol_;
}
@property (nonatomic, readwrite, assign) id delegate;
@property (nonatomic, readwrite, retain) Protocol *protocol;
- (id)initWithProtocol:(Protocol *)aProtocol delegate:(id)aDelegate;
@end
@implementation RNDelegateTrampoline
- (id)initWithProtocol:(Protocol *)aProtocol delegate:(id)aDelegate {
if ((self = [super init])) {
protocol_ = [aProtocol retain];
delegate_ = aDelegate;
}
return self;
}
- (void)dealloc {
[protocol_ release], protocol_ = nil;
delegate_ = nil;
[super dealloc];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
{
struct objc_method_description desc = protocol_getMethodDescription(self.protocol, selector, YES, YES);
if (desc.name == NULL) {
desc = protocol_getMethodDescription(self.protocol, selector, NO, YES);
}
if (desc.name == NULL) {
[self doesNotRecognizeSelector:selector];
return nil;
}
else {
return [NSMethodSignature signatureWithObjCTypes:desc.types];
}
}
- (void)forwardInvocation:(NSInvocation *)invocation {
if ([[self delegate] respondsToSelector:[invocation selector]]) {
[invocation invokeWithTarget:[self delegate]];
}
}
@synthesize delegate = delegate_;
@synthesize protocol = protocol_;
@end
:
@property (nonatomic, readwrite, retain) id delegateTramp;
self.delegateTramp = [[[RNDelegateTrampoline alloc] initWithProtocol:@protocol(ThisObjectDelegate) delegate:aDelegate] autorelease];
...
[self.delegateTramp thisObject:self didSomethingWith:x];
, id, RNDelegateTrampoline . , , . id . , , . .