• 直接调用对象方法的两种方式


    关于直接调用方法和给对象发送消息调用方法(即perfromSelector和NSInvocation)

    performSelector是运行时系统负责去找方法的,在编译时候不做任何校验;如果直接调用编译是会自动校验。如果imageDownloader:didFinishWithImage:image:不存在,那么直接调用 在编译时候就能够发现(借助Xcode可以写完就发现),但是使用performSelector的话一定是在运行时候才能发现(此时程序崩溃);Cocoa支持在运行时向某个类添加方法,即方法编译时不存在,但是运行时候存在,这时候必然需要使用performSelector去调用。所以有时候如果使用了performSelector,为了程序的健壮性,会使用检查方法

    - (BOOL)respondsToSelector:(SEL)aSelector;

    转自 http://blog.csdn.net/meegomeego/article/details/20041887

    1、perfromSelector

    2、NSInvocation 

    NSInvocation 比起 perfromSelector 的好处,可以传递不止两个参数

    1)NSInvocation使用方式一

        //    1、创建“方法调用”对象:NSInvocation(invocation 的英文含义:调用)
        //    1>、设置“方法签名”对象,到底怎么理解这个方法签名呢???
        NSMethodSignature *signature = [ViewController instanceMethodSignatureForSelector:@selector(sendMessageWithNumber:andContent:status:)];
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
        //    2>、要执行谁里面的---
        invocation.target = self;
        //    3>、什么方法
        
        invocation.selector = @selector(sendMessageWithNumber:andContent:status:);
        //    4>、传递的参数
        // 注意:自定义的参数索引从2开始, 0是self /  1是_cmd;
        //      方法签名中保存的方法名称, 必须和invocation的selector中保存的方法名称一样;
        NSString *number = @"10086";
        NSString *content = @"你好";
        NSString *status = @"发送成功";
        
        [invocation setArgument:&number atIndex:2];
        [invocation setArgument:&content atIndex:3];
        [invocation setArgument:&status atIndex:4];
        
        //    2、执行调用
        [invocation invoke];

    2)NSInvocation方式二:给NSObject添加一个分类

    .h文件

    #import <Foundation/Foundation.h>
    
    @interface NSObject (CY)
    
    - (id)performSelector:(SEL)aSelector withObjects:(NSArray *)objects;
    
    @end

    .m文件

    #import "NSObject+CY.h"
    
    @implementation NSObject (CY)
    
    
    - (id)performSelector:(SEL)aSelector withObjects:(NSArray *)objects
    {
        // 签名中保存了方法的名称/参数/返回值类型
        // 注意: 签名一般是用来设置参数和获取返回值的, 和方法的调用没有太大的关系
        NSMethodSignature  *signature = [[self class] instanceMethodSignatureForSelector:aSelector];
        
        // 0.判断传入的方法是否存在, 如果不存在就进行相应处理
        if (signature == nil) {
            // 如果方法不存在, 就抛出一个异常
    //        @throw  [NSException exceptionWithName:@"小码哥课堂特定异常" reason:@"你太SB了" userInfo:nil];
            NSString *info = [NSString stringWithFormat:@"%@方法找不到", NSStringFromSelector(aSelector)];
            [NSException raise:@"特定异常" format:info, nil];
    //        return nil;
        }
        
        // 1.创建一个NSInvocation对象
        // NSInvocation中保存了方法所属的对象/方法名称/参数/返回值
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
        invocation.target = self;
        invocation.selector = aSelector;
        // 注意: 如果需要通过遍历给invocation设置参数, 那么不能遍历objects数组
        // 因为objects数组的长度是不可控
        // 注意: 通过numberOfArguments方法获取的参数个数, 是包含self和_cmd的
        NSUInteger argsCount = signature.numberOfArguments - 2; // 3
        NSUInteger arrCount = objects.count; // 4  2
        NSUInteger count = MIN(argsCount, arrCount);
    //    for (int i = 0; i < objects.count; i++) {
        for (int i = 0; i < count; i++) {
            id obj = objects[i];
            // 判断需要设置的参数是否是NSNull, 如果是就设置为nil
            if ([obj isKindOfClass:[NSNull class]]) {
                obj = nil;
            }
            [invocation setArgument:&obj atIndex:i + 2];
        }
        
        // 2.调用NSInvocation对象的invoke方法
        [invocation invoke];
    
        // 3.获取方法的返回值
        id res = nil;
        // 3.1判断当前调用的方法, 是否有返回值
    //    NSLog(@"methodReturnType = %s", signature.methodReturnType);
    //    NSLog(@"methodReturnLength = %zd", signature.methodReturnLength);
        if (signature.methodReturnLength != 0) {
            [invocation getReturnValue:&res];
        }
        return res;
    }
    @end
  • 相关阅读:
    malloc和new的区别
    Http协议解析
    Linux基础命令-history
    Linux基础命令-last
    Linux基础命令-who
    Linux基础命令-free
    Linux基础命令-uptime
    Linux基础命令-uname
    Linux基础命令-ifconfig
    Linux基础命令-killall
  • 原文地址:https://www.cnblogs.com/imChay/p/5641649.html
Copyright © 2020-2023  润新知