`

消息转发: methodSignatureForSelector + forwardInvocation

阅读更多

      在object-C中,我们可以向一个实例发送消息,这类似于其他编程语法中的方法调用,实例收到消息后,会进行一些处理:例如实例收到消息后,如果能respondsToSelector,那么就调用相应的方法,如果不能response一般情况会crash。下面通过方面减少这种crash。

     

      实例收到消息后,一般的处理流程如下:

      1,发送消息,如[obj methodB];

      2,系统会检查是否能response这个消息

      3,如果能response则调用相应方法,不能则抛出异常。

 

      第三步中,默认抛出异常,通过重新NSObject的方法methodSignatureForSelector和forwardInvocation能够在实例不response这个消息时,将消息交由其他类实例进行处理,减少crash的几率。当检测到实例不能相应对应的消息时,系统会发出methodSignatureForSelector消息,询问这个消息是否有效,有效就返回方法签名之类的信息,无效返回nil(返回nil抛出异常);如果不是nil,接下来会发送forwardInvocation消息,我们能够在forwardInvocation消息中将消息委托给其他类实例进行处理。以下用代码进行说明:

ObjA.h

@interface ObjA
@end

ObjA.m

#import "ObjA.h"
#import "ObjB.h"

@implementation ObjA
{
      ObjB   *_b;
}

- (void)dealloc
{
      [_b release], _b = nil;
      
      [super dealloc];
}

- (id)init
{
      self = [super init];
      if ( self ) {
           _b = [[ObjB alloc] init];
      }
      return self;
}

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

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
      if ( [_b respondsToSelector:[anInvocation selector]] ) {
            [anInvocation invokeWithTarget:_b];
      } else {
            [super forwardInvocation:anInvocation];
      }
}

ObjB.h

@interface ObjB
- (void)methodB;
@end

 

ObjB.m

#import "ObjB.h"

@implementation ObjB

- (void)methodB
{
      NSLog(@"methodB");
}

@end

 

 调用代码:

[objA methodB];
// [objA performSelector:@selector(methodB) withObject:nil];

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics