Kar*_*arl 19 iphone objective-c selector nsinvocation
我无法让forwardInvocation工作.出于某种原因,Objective-C运行时完全忽略了我的forwardInvocation:方法并抛出了无法识别的选择器异常.
我的测试代码如下:
@interface InvocationTest : NSObject
{
}
+ (void) runTest;
@end
@interface FullClass: NSObject
{
int value;
}
@property(readwrite,assign) int value;
@end
@implementation FullClass
@synthesize value;
@end
@interface SparseClass: NSObject
{
}
@end
@implementation SparseClass
- (void)forwardInvocation:(NSInvocation *)forwardedInvocation
{
NSLog(@"ForawrdInvocation called");
FullClass* proxy = [[[FullClass alloc] init] autorelease];
proxy.value = 42;
[forwardedInvocation invokeWithTarget:proxy];
}
@end
@implementation InvocationTest
+ (void) runTest
{
SparseClass* sparse = [[[SparseClass alloc] init] autorelease];
NSLog(@"Value = %d", [sparse value]);
}
@end
Run Code Online (Sandbox Code Playgroud)
我正在处理来自以下资源的信息:
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtForwarding.html#//apple_ref/doc/uid/TP40008048-CH105 http://cocoawithlove.com/2008/ 03 /构建-NSInvocation的换任何-message.html
据我所知,当我调用[稀疏值]时,运行时应该在SparseClass的实例上调用forwardInvocation:但它会被完全忽略:
- [SparseClass值]:发送到实例0x4b1c4a0的无法识别的选择器***由于未捕获的异常'NSInvalidArgumentException'终止应用程序,原因:' - [SparseClass值]:无法识别的选择器发送到实例0x4b1c4a0'
Jil*_*ouc 38
您还必须覆盖- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector以使其正常工作.
我猜
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
return [FullClass instanceMethodSignatureForSelector:aSelector];
}
Run Code Online (Sandbox Code Playgroud)
应该可以.
e.J*_*mes 26
从NSObject文档:
重要说明:要响应您的对象本身无法识别的方法,您必须覆盖
methodSignatureForSelector:除此之外的方法forwardInvocation:.转发消息的机制使用从中获取的信息methodSignatureForSelector:来创建NSInvocation要转发的对象.您的重写方法必须为给定的选择器提供适当的方法签名,方法是预先制定一个或通过询问另一个对象.
并且,从运行时文档:
...如果一个对象转发它收到的任何远程消息,它应该有一个版本
methodSignatureForSelector:,可以返回最终响应转发消息的方法的准确描述; 例如,如果一个对象能够将消息转发给其代理,您将按methodSignatureForSelector:如下方式实现:
- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector
{
NSMethodSignature* signature = [super methodSignatureForSelector:selector];
if (!signature) {
signature = [surrogate methodSignatureForSelector:selector];
}
return signature;
}
Run Code Online (Sandbox Code Playgroud)
注意:请参阅Jilouc的正确实施答案methodSignatureForSelector:.