继承自NSObject的不常用又很有用的函数- 函数调用2

补充:respondsToSelector

+(BOOL)respondsToSelector:(SEL)aSelector

这个函数大家再熟悉不过了,用来检查对象是否实现了某函数。

此函数通常是不需要重载的,但是在动态实现了查找过程后,需要重载此函数让对外接口查找动态实现函数的时候返回YES,保证对外接口的行为统一。

 - (BOOL) respondsToSelector:(SEL)aSelector
    {
       if (@selector(setTitle:) == aSelector ||
       @selector(title) == aSelector ||
       @selector(setAuthor:) == aSelector ||
       @selector(author) == aSelector)
      {
        return YES;
      }

       return [super respondsToSelector: aSelector];
    }

  //全局函数
 1.void dynamicMethodIMP(id self, SEL _cmd)
        {
           // implementation ....
        }

 2.+ (BOOL) resolveInstanceMethod:(SEL)aSEL
       {
        if (aSEL == @selector(resolveThisMethodDynamically))
        {
            class_addMethod([self class], aSEL, (IMP) dynamicMethodIMP, "v@:");
            return YES;
         }
         return [super resolveInstanceMethod:aSel];
       }

  //将消息转出某对象
3.- (id)forwardingTargetForSelector:(SEL)aSelector
      {
       NSLog(@"MyTestObject _cmd: %@", NSStringFromSelector(_cmd));

        NoneClass *none = [[NoneClass alloc] init];
        if ([none respondsToSelector: aSelector]) {
          return none;
       }

       return [super forwardingTargetForSelector: aSelector];
      }

4.- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
    {
      NSString *sel = NSStringFromSelector(selector);
      if ([sel rangeOfString:@"set"].location == 0) {
        //动态造一个 setter函数
        return [NSMethodSignature signatureWithObjCTypes:"v@:@"];
      } else {
        //动态造一个 getter函数
        return [NSMethodSignature signatureWithObjCTypes:"@@:"];
      }
   }

5.- (void)forwardInvocation:(NSInvocation *)invocation
      {
       //拿到函数名
       NSString *key = NSStringFromSelector([invocation selector]);
       if ([key rangeOfString:@"set"].location == 0) {
          //setter函数形如 setXXX: 拆掉 set和冒号 
          key = [[key substringWithRange:NSMakeRange(3, [key length]-4)] lowercaseString];
          NSString *obj;
          //从参数列表中找到值
          [invocation getArgument:&obj atIndex:2];
          [data setObject:obj forKey:key];
        } else {
          //getter函数就相对简单了,直接把函数名做 key就好了。
          NSString *obj = [data objectForKey:key];
          [invocation setReturnValue:&obj];
        }
      }