2011-01-06 2 views
19

У меня возникли проблемы с продвижением вперед. По какой-то причине время выполнения Objective-C полностью игнорирует мой метод forwardInvocation: и генерирует исключение исключенного исключения.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'

ответ

36

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

Я думаю

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

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

+1

Awesome! Работал как шарм. – Karl

24

Из документации 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:.

+13

Я думаю, что руководство по программированию Runtime от Apple не справляется с этой проблемой. В разделе «Переадресация» они ничего не говорят о необходимости «methodSignatureForSelector:» с 'forwardInvocation:'. Чтобы найти этот лакомый кусочек, прокрутите 3 раздела вниз, чтобы узнать, что вам нужно реализовать метод раздела. – DBD

 Смежные вопросы

  • Нет связанных вопросов^_^