我想在我的SZNUnmanagedReference类上使用消息转发。它具有以下属性:
@property (nonatomic, strong) NSSet *authors;
@property (nonatomic, strong) SZNReferenceDescriptor *referenceDescriptor;
基本上,当UnmanagedReference实例接收到消息
authorsString
时,应将其转发到referenceDescriptor
,后者具有一个名为- (NSString *)authorsStringWithSet:(NSSet *)authors
的方法。因此,我用
SZNUnmanagedReference.m
编写了此代码:- (void)forwardInvocation:(NSInvocation *)anInvocation {
SEL aSelector = anInvocation.selector;
if ([NSStringFromSelector(aSelector) isEqualToString:NSStringFromSelector(@selector(authorsString))]) {
NSMethodSignature *signature = [self.referenceDescriptor methodSignatureForSelector:@selector(authorsStringWithSet:)];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
NSSet *authors = [NSSet setWithSet:self.authors];
[invocation setSelector:@selector(authorsStringWithSet:)];
[invocation setArgument:&authors atIndex:2];
[invocation setTarget:self.referenceDescriptor];
[invocation invoke];
} else {
[self doesNotRecognizeSelector:aSelector];
}
}
- (BOOL)respondsToSelector:(SEL)aSelector {
if ([super respondsToSelector:aSelector]) {
return YES;
} else if ([NSStringFromSelector(aSelector) isEqualToString:NSStringFromSelector(@selector(authorsString))] && [self.referenceDescriptor respondsToSelector:@selector(authorsStringWithSet:)]) {
return YES;
} else {
return NO;
}
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
NSMethodSignature *signature = [super methodSignatureForSelector:aSelector];
if (!signature) {
signature = [self.referenceDescriptor methodSignatureForSelector:@selector(authorsStringWithSet:)];
}
return signature;
}
似乎一切正常,
SZNReferenceDescriptor
类中的代码已执行。但是,我不知道如何取回
authorsString
。如果我正确理解了文档,我认为referenceDescriptor
应该会将结果发送回邮件的原始发件人。但这似乎不起作用。在我的测试类中,[unmanagedReference authorsString]
返回nil
。 最佳答案
问题在于您正在构造一个新的NSInvocation
对象,该对象的返回值在需要的位置(消息分派(dispatch)“堆栈”的“顶部”)无法访问。运行时仅知道它为您创建的那个(forwardInvocation:
的参数;这是它将使用其返回值的那个。那么,您要做的就是设置其返回值:
- (void)forwardInvocation:(NSInvocation *)anInvocation {
if (anInvocation.selector == @selector(authorsString)) {
id retVal = [self.referenceDescriptor authorsStringWithSet:self.authors];
[anInvocation setReturnValue:&retVal]; // ARC may require some memory-qualification casting here; I'm compiling this by brain at the moment
} else {
[super forwardInvocation:anInvocation];
}
}
实际上,实际上没有必要创建该新调用。由于您所需的只是方法的返回值,因此您可以直接发送消息(如果您只是在
authorsString
上实现了SZNUnmanagedReference
,而不是使用转发机制,也可以这样做)。另外,请注意,无需将选择器与字符串进行转换以进行比较-可以使用相等运算符直接比较
SEL
。关于objective-c - forwardInvocation : the return value gets lost,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11457651/