给分类(Category)添加属性

作者: 碧霄问鼎 | 来源:发表于2015-06-21 18:52 被阅读20033次

    遇到一个问题,写了一个分类,但原先类的属性不够用。添加一个属性,调用的时候崩溃了,说是找不到getter、setter方法。查了下文档发现,OC的分类允许给分类添加属性,但不会自动生成getter、setter方法。有没有解决方案呢?有,通过运行时建立关联引用。接下来以添加一个这样的属性为例:

    @property (nonatomic, copy) NSString *str;
    

    1、引入运行时头文件。
    #import <objc/runtime.h>
    2、在匿名分类或者头文件中添加属性。区别是:匿名分类中添加的是私有属性,只在本类中可以使用,类的实例中不可以使用。头文件中添加的在类的实例中也可以使用。

    //分类的头文件
    @interface ClassName (CategoryName)
    //我要添加一个实例也可以访问的变量所以就写在这里了
    @property (nonatomic, strong) NSString *str;
    @end
    
    //匿名分类
    @interface ClassName ()
    
    @end
    

    3、在实现里面写要添加属性的getter、setter方法。

    @implementation ClassName (CategoryName) 
    
    -(void)setStr:(NSString *)str  
    {  
        objc_setAssociatedObject(self, &strKey, str, OBJC_ASSOCIATION_COPY);  
    }  
    
    -(NSString *)str  
    {  
        return objc_getAssociatedObject(self, &strKey);  
    }
    @end 
    

    setStr:方法中使用了一个objc_setAssociatedObject的方法,这个方法有四个参数,分别是:源对象,关联时的用来标记是哪一个属性的key(因为你可能要添加很多属性),关联的对象和一个关联策略。

    用来标记是哪一个属性的key常见有三种写法,但代码效果是一样的,如下:

    //利用静态变量地址唯一不变的特性
    1、static void *strKey = &strKey;
    
    2、static NSString *strKey = @"strKey"; 
    
    3、static char strKey;
    

    关联策略是个枚举值,解释如下:

    enum {
        OBJC_ASSOCIATION_ASSIGN = 0, //关联对象的属性是弱引用 
         
        OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, //关联对象的属性是强引用并且关联对象不使用原子性
    
        OBJC_ASSOCIATION_COPY_NONATOMIC = 3, //关联对象的属性是copy并且关联对象不使用原子性
    
        OBJC_ASSOCIATION_RETAIN = 01401, //关联对象的属性是copy并且关联对象使用原子性
    
        OBJC_ASSOCIATION_COPY = 01403 //关联对象的属性是copy并且关联对象使用原子性
    };
    

    4、完成后的整体代码如下:

    .h文件

    //分类的头文件
    @interface ClassName (CategoryName)
    @property (nonatomic, strong) NSString *str;
    @end
    

    .m文件

    //实现文件
    #import "ClassName + CategoryName.h"
    #import <objc/runtime.h>
    
    static void *strKey = &strKey;
    
    @implementation ClassName (CategoryName) 
    -(void)setStr:(NSString *)str  
    {  
        objc_setAssociatedObject(self, & strKey, str, OBJC_ASSOCIATION_COPY);  
    }  
    
    -(NSString *)str  
    {  
        return objc_getAssociatedObject(self, &strKey);  
    }
    @end 
    

    下篇见~

    相关文章

      网友评论

      • Stroman:你能解释一下什么是strKey吗?为什么要用它?换成别的类型可以吗?
      • SoaringHeart:分类创建block对象的内存释放和循环引用问题 如何处理
      • 70bf62aea5ca:直接用extension不就完了吗?搞这么麻烦。。。
        花前月下:分类不是你想用 想用就能用 ~
      • 一夜暴富两夜也行:按照你的方法给baseVC添加属性,咋还崩了呢?
      • Bearger:0.0 ,分类中添加属性不好~!
        Lol刀妹:@Bearger 为什么:flushed:什么情况下分类中添加属性不好
      • 高手世界:为什么给UIView增加分类添加 x,y,width,height等属性时只需要重写set,get方法,不用设置关联属性啊,
        Fight_ing:UIView(frame)分类不用runtime动态绑定的原因是:我们只需要用到自己定义属性的setter,
        getter方法去设置,返回UIView***“本身就有的属性”***。而正常情况下,自己定义的属性,setter是设置自定义属性的值,getter也是返回自定义属性的值,而此时分类是没有 “_” 开头的自定义属性字
        段的,必须动态绑定
        观星:可以参考这个解释 http://www.jianshu.com/p/39f5f29fb773
        ea66a8441989:请问你的问题解决了吗?如果解决了,可以给我解释一下吗?因为我也遇到了同样的问题!
      • 卧龙小:先赞,成功解决了我的问题,我在分类中添加了个Block ,提个问题,在分类中添加属性这样做好么?
        6585f9d7f147:这样做不好
      • __Lex:为什么 我添加的属性 不走set和get方法啊
      • e8dfad189e00:帮到我了 非常感谢!🙏
      • gogo小小酥:如果添加基本数据类型的属性怎么写呢
        WhisperKarl:@Ninesuns 这个帮助到我啦 感谢!
        gogo小小酥:@Ninesuns 明白!谢了
        3ba5106238e5:@gogo小小酥 setter时把数据封装成对象
        NSNumber *someObject = [NSNumber numberWithInt:100]
        getter获取时再 return [someObject integerValue]
      • i顺颂时宜:如果添加的属性为 NSInteger类型的,setter和getter怎么写呢??主要是setter的关联策略。
        i顺颂时宜:NSInteger 应该封装成NSnumber,而且关联政策需要写成强引用的。
      • 三斤叔:到底分类可不可以加属性?怎么自己的类可以
        天下无贼:@三斤叔 分类是对已经有的类 添加新方法 和属性 跟你自己新建的类 不一样

      本文标题:给分类(Category)添加属性

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