美文网首页Objective-C Runtime
runtime简单使用之动态添加属性

runtime简单使用之动态添加属性

作者: Alexander | 来源:发表于2016-03-08 22:20 被阅读1295次

    runtime简单使用之给系统类动态添加属性

    前言

    • 1, 给类动态添加属性,实质就是让一个属性与某个对象产生关联的关系.值得注意的一点: 使用该功能的前提是给系统的类添加属性,如果是自定义的类添加属性,就没有必要用到runtime了.

    • 2, 背景: 给系统的NSObject类动态添加一个name属性.

    1, 创建NSObject对象

    #import "ViewController.h"
    #import "NSObject+property.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        NSObject *objc = [[NSObject alloc] init];
        objc.name = @"WilliamAlex";
    
        NSLog(@"%@",objc.name);
    }
    @end
    
    
    • 注意 : 如果直接定义一个WGPerson类,在WGPerson类中声明并实现name属性,这样添加属性直接添加就是了,没有必要使用runtime来动态添加.一般的做法是添加一个分类,在分类中声明一个name属性,然后手动写setter和getter方法,使用runtime保存name属性并与NSObject产生关联.

    2, 创建一个分类

    // 在分类中声明一个属性时,只会生成setter和getter方法的声明,并不能生成setter和getter方法的实现以及带下划线的成员变量.所以, 在分类中有两种方式声明一个属性
    
    // 第一种写法
    @property(nonatomic, strong) NSString *name;
    
    // 第二种写法 : 原因是在分类中声明属性只会生成setter和getter的声明
    @property NSString *name;
    
    
    • 实现setter和getter方法
    #import "NSObject+property.h"
    #import <objc/message.h>
    
    @implementation NSObject (property)
    
    - (void)setName:(NSString *)name
    {
        // Associated : |əˈsəʊʃɪeɪt|关联的意思
    
        /*
         产生关联,让某个对象(name)与当前对象的属性(name)产生关联
         参数1: id object :表示给哪个对象添加关联
         参数2: const void *key : 表示: id类型的key值(以后用这个key来获取属性) 属性名
         参数3: id value : 属性值
         参数4: 策略, 是个枚举(点进去,解释很详细)
         */
    
        objc_setAssociatedObject(self, "Alex", name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
    }
    
    - (NSString *)name
    {
        return objc_getAssociatedObject(self, "Alex");
    }
    
    // 下面是策略(是个枚举值)的类型
    OBJC_ASSOCIATION_ASSIGN = 0,
    < Specifies a weak reference to the associated object.
    
    OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1,
    < Specifies a strong reference to the associated object.
                                              The association is not made atomically.
    
    OBJC_ASSOCIATION_COPY_NONATOMIC = 3,
    < Specifies that the associated object is copied.
                                           The association is not made atomically
    
    OBJC_ASSOCIATION_RETAIN = 01401,
    < Specifies a strong reference to the associated object.
                                             The association is made atomically.
    
    OBJC_ASSOCIATION_COPY = 01403
    < Specifies that the associated object is copied.
                                          The association is made atomically.
    
    
    @end
    
    
    • 打印结果
    2016-03-08 21:58:52.232 sasass[2172:73513] WilliamAlex
    
    
    • 总结 :

    问题 : 为什么我们会用runtime方法来给系统的类动态添加属性? 直接在分类的.m文件中定义一个全局的NSString *_name;也可以打印出结果啊!为什么不能那样做呢

    • 具体实现
    // 其他保持一样
    #import "NSObject+property.h"
    #import <objc/message.h>
    
    NSString *_name;
    @implementation NSObject (property)
    
    - (void)setName:(NSString *)name
    {
        _name =name;
    
    }
    
    - (NSString *)name
    {
        return _name;
    }
    
    @end
    
    • 打印结果
    2016-03-08 21:58:52.232 sasass[2172:73513] WilliamAlex
    
    

    答 : 属性保存的地址不同,如果使用问题中所述的那样,虽然可以打印出结果,但是当objc销毁了,objc.name并不会随着它的销毁而销毁.这样就不是关联关系了.既然是添加属性,那么当objc销毁了,objc.name也需要随之销毁,如果直接在分类中实现setter和getter方法,虽然可以打印出字符串,但是并没有与之产生关联,所以这时候就需要使用东岸runtime,那么就需要将某个属性保存到条用它的对象里.给哪个对象添加属性,那么就将之保存到谁里面.

    相关文章

      网友评论

      • Amok校长: objc_setAssociatedObject(self, "Alex", name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        中的 "Alex"是什么意思?我给UIImage添加name属性总是失败
        Alexander:@kirs 那是名称:sweat:

      本文标题:runtime简单使用之动态添加属性

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