forwardInvocation не вызывается? - PullRequest
       36

forwardInvocation не вызывается?

19 голосов
/ 07 января 2011

У меня проблемы с получением 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 при вызове [sparseзначение], но оно полностью игнорируется:

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

Ответы [ 2 ]

38 голосов
/ 07 января 2011

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

Я думаю,

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

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

25 голосов
/ 07 января 2011

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

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

И, из документации времени выполнения :

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

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

Примечание: См. ответ Джилука для правильной реализации methodSignatureForSelector:.

...