iOS runtime学习(二)

作者: 在这蓝色天空下 | 来源:发表于2016-11-22 16:19 被阅读103次

    <a href="http://www.jianshu.com/p/dedba04a104d">iOS runtime学习(一)</a>

    1、发送消息

    方法调用的本质,就是让对象发送消息。

    objc_msgSend,只有对象才能发送消息,因此以objc开头.

    使用消息机制前提,必须导入#import <objc/message.h>

    消息机制简单使用

    消息机制原理:对象根据方法编号SEL去映射表查找对应的方法实现

        // 创建person对象
        BDPerson *p = [[BDPerson alloc] init];
        
        // 调用对象方法
        [p eat];
        // SEL:方法编号,根据方法编号就可以找到对应方法实现
        [p performSelector:@selector(eat)];
        
        // 本质:让对象发送消息
        objc_msgSend(p, @selector(eat));
        
        // 调用类方法的方式:两种
        // 第一种通过类名调用本质类名转换成类对象
        [BDPerson eat];
        // 第二种通过类对象调用
        [[BDPerson class] eat];
        
        [BDPerson performSelector:@selector(eat)];
        // 用类名调用类方法,底层会自动把类名转换成类对象调用
        // 本质:让类对象发送消息
        objc_msgSend([BDPerson class], @selector(eat));
    

    错误代码Too many arguments to function call, expected 0, have 3

    解决方案:

    选中项目 - Project - Build Settings - ENABLE_STRICT_OBJC_MSGSEND 将其设置为 NO 即可


    2、动态创建类,并添加属性和方法

    - (void)createClass  
    { 
        Class MyClass = objc_allocateClassPair([NSObject class], "myclass", 0);
        //添加一个NSString的变量,第四个参数是对其方式,第五个参数是参数类型
        if (class_addIvar(MyClass, "itest", sizeof(NSString *), 0, "@")) {
            NSLog(@"add ivar success");
        }
        //myclasstest是已经实现的函数,"v@:"这种写法见参数类型连接
        class_addMethod(MyClass, @selector(myclasstest:), (IMP)myclasstest, "v@:");
        //注册这个类到runtime系统中就可以使用他了
        objc_registerClassPair(MyClass);
        //生成了一个实例化对象
        id myobj = [[MyClass alloc] init];
        NSString *str = @"asdb";
        //给刚刚添加的变量赋值
        //    object_setInstanceVariable(myobj, "itest", (void *)&str);在ARC下不允许使用
        [myobj setValue:str forKey:@"itest"];
        //调用myclasstest方法,也就是给myobj这个接受者发送myclasstest这个消息
        [myobj myclasstest:10];
    }
    
    //这个方法实际上没有被调用,但是必须实现否则不会调用下面的方法
    - (void)myclasstest:(int)a
    {
        
    }
    
    //调用的是这个方法
    static void myclasstest(id Self, SEL _cmd, int a) //self和_cmd是必须的,在之后可以随意添加其他参数
    {
        
        Ivar v = class_getInstanceVariable([Self class], "itest");
        //返回名为itest的ivar的变量的值
        id o = object_getIvar(Self, v);
        //成功打印出结果
        NSLog(@"%@", o);
        NSLog(@"int a is %d", a);
    }
    
    

    相关文章

      网友评论

        本文标题:iOS runtime学习(二)

        本文链接:https://www.haomeiwen.com/subject/oaoppttx.html