Подтвердить что ты не робот

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

Я отлаживаю информацию из следующих ресурсов:

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtForwarding.html#//apple_ref/doc/uid/TP40008048-CH105 http://cocoawithlove.com/2008/03/construct-nsinvocation-for-any-message.html

Насколько я могу судить, время выполнения должно быть вызвано forwardInvocation: на экземпляре SparseClass, когда я вызываю [разреженное значение], но он полностью игнорируется:

- [Значение SparseClass]: непризнанный селектор, отправленный в экземпляр 0x4b1c4a0 *** Завершение приложения из-за неотображенного исключения "NSInvalidArgumentException", причина: '- [Значение SparseClass]: непризнанный селектор, отправленный экземпляру 0x4b1c4a0'

4b9b3361

Ответ 1

Вы также должны переопределить - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector, чтобы заставить его работать.

Думаю,

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    return [FullClass instanceMethodSignatureForSelector:aSelector];
}

должно быть в порядке.

Ответ 2

Из NSObject документация:

Важно. Чтобы ответить на методы, которые ваш объект сам не распознает, вы должны переопределить methodSignatureForSelector: в дополнение к forwardInvocation:. Механизм пересылки сообщений использует информацию, полученную из methodSignatureForSelector:, чтобы создать объект NSInvocation для пересылки. Ваш метод переопределения должен предоставить соответствующую сигнатуру метода для данного селектора либо путем предварительной форматирования, либо путем запроса другого объекта для одного.

И из runtime документация:

... если объект пересылает любые удаленные сообщения, которые он получает, он должен иметь версию methodSignatureForSelector:, которая может возвращать точное описание методов, которые в конечном счете отвечают на пересылаемые сообщения; например, если объект способен пересылать сообщение своему суррогату, вы должны реализовать methodSignatureForSelector: следующим образом:

- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector 
{ 
    NSMethodSignature* signature = [super methodSignatureForSelector:selector];
    if (!signature) {
       signature = [surrogate methodSignatureForSelector:selector];
    } 
    return signature;
}

Примечание. См. Jilouc answer для правильной реализации methodSignatureForSelector:.