forwardInvocation: se pierde el valor de retorno

Quiero utilizar el reenvío de posts en mi class SZNUnmanagedReference. Tiene estas properties:

@property (nonatomic, strong) NSSet *authors; @property (nonatomic, strong) SZNReferenceDescriptor *referenceDescriptor; 

Básicamente, cuando una instancia de UnmanagedReference recibe el post authorsString , debe reenviarlo a referenceDescriptor , que tiene un método denominado - (NSString *)authorsStringWithSet:(NSSet *)authors .

Entonces, escribí esto en 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; } 

Todo parece funcionar, se ejecuta el código en la class SZNReferenceDescriptor . Sin embargo, no sé cómo recuperar los authorsString . Si entendí la documentation correctamente, creo que se supone que la referenceDescriptor debe enviar el resultado al remitente original del post. Pero parece que no funciona. En mi class de testing, [unmanagedReference authorsString] devuelve nil .

El problema es que estás construyendo un nuevo object NSInvocation , cuyo valor de retorno no es accesible en el punto donde se necesita (la "parte superior" del post despacha "stack"). El time de ejecución solo conoce el que creó para usted (el argumento para forwardInvocation: ese es el valor de retorno que usará. Todo lo que tiene que hacer, entonces, es establecer su valor de retorno:

 - (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]; } } 

De hecho, no hay necesidad de crear esa nueva invocación; ya que todo lo que necesita es el valor de retorno del método, simplemente puede enviar el post directamente (lo que también podría hacer si acaba de implementar authorsString en SZNUnmanagedReference , en lugar de utilizar el mecanismo de reenvío).

Además, tenga en count que no hay necesidad de convertir selectores en cadenas y desde cadenas para compararlas: los SEL pueden compararse directamente usando el operador de igualdad.