美文网首页
【知识总结】category探索 — 如何在分类中添加一个属性(

【知识总结】category探索 — 如何在分类中添加一个属性(

作者: 小子爱搞事 | 来源:发表于2017-01-12 16:33 被阅读38次

    添加属性的本质:

    对象添加属性,并不是在对象中为属性分配响应的内存,而是通过一个指针指向这个属性,本质就是关联这个属性
    因此,在分类中我们可以通过关联的方式添加属性


    我们新建一个 UIView 的分类,在分类中添加属性和方法

    @interface UIView (Extension)
    @property (nonatomic, strong) NSString *property;
    - (void)show;
    @end
    

    在 m 文件中实现 show 方法

    #import "UIView+Extension.h"
    @implementation UIView (Extension)
    - (void)show
    {
    NSLog(@"%@", self.property);
    }
    
    @end
    

    下面,我们来测试一下,在viewController中使用我们的分类

    - (void)viewDidLoad {
    [super viewDidLoad];
    
    UIView *view = [[UIView alloc] init];
    view.property = @"我是分类中添加的属性";
    [view show];
    }
    

    运行,可以看到程序奔溃了,查看奔溃信息:

    奔溃信息提示,我们的 分类中添加的属性, setProperty:方法没有实现

    接下来,我们尝试实现setProperty:方法,但是会遇到下面的问题

    系统提示我们使用 @dynamic 实现分类这个分类

    接着,我们尝试使用 @dynamic 实现,如下:

    上面,我们一直才尝试实现 setProperty: 方法,但是由于分类的特殊性
    在分类中声明@property,只会生成方法的声明,不会生成方法的实现和带有_下划线的成员变量
    而且我们尽量去尝试自己实现,系统也是不允许我们这么做的

    于是我们使用runtime来实现为分类添加属性这一需求


    使用到运行时,首先我们要导入 <objc/runtime.h> 头文件

    #import "UIView+Extension.h"
    #import <objc/runtime.h>
    
    @implementation UIView (Extension)
    
    - (void)setProperty:(NSString *)property
    {
    NSLog(@"实现 setProperty 方法");
    objc_setAssociatedObject(self, @selector(property), property, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
    }
    
    - (NSObject *)property {
    
    return objc_getAssociatedObject(self, @selector(property));
    
    }
    
    - (void)show
    {
    NSLog(@"show:%@", self.property);
    }
    @end
    

    运行程序,查看结果

    我们已经成功的为分类添加了一个属性

    分析上面用到的两个运行时方法

    void objc_setAssociatedObject(id object, const voidvoid *key, id value, objc_AssociationPolicy policy)
    
    id objc_getAssociatedObject(id object, const voidvoid *key)
    
    void objc_removeAssociatedObjects(id object)
    

    把一个value关联到另外一个object里,类似NSDictionary的 setValue:forKey 。
    用 objc_setAssociatedObject 关联以后,用 objc_getAssociatedObject 取出使用。
    objc_AssociationPolicy 属性 是设定该value在object内的属性,即 assgin, (retain,nonatomic)...等

    1. //policy
    2. enum {
    3. OBJC_ASSOCIATION_ASSIGN = 0, /**< Specifies a weak reference to the associated object. */
    4. OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object.
    5. * The association is not made atomically. */
    6. OBJC_ASSOCIATION_COPY_NONATOMIC = 3, /**< Specifies that the associated object is copied.
    7. * The association is not made atomically. */
    8. OBJC_ASSOCIATION_RETAIN = 01401, /**< Specifies a strong reference to the associated object.
    9. * The association is made atomically. */
    10. OBJC_ASSOCIATION_COPY = 01403 /**< Specifies that the associated object is copied.
    11. * The association is made atomically. */
    12. };
    13.
    14. /// Type to specify the behavior of an association.
    15. typedef uintptr_t objc_AssociationPolicy;
    

    我们可以通过这个运行方法,实现 button 事件的 block 实现

    相关资料:
    用objc/runtime给类别扩展属性 http://www.jianshu.com/p/84de8a931adf
    objc_setAssociatedObject与Block的简单使用 http://www.jianshu.com/p/35df1ba1f107


    有一个推荐添加读写属性的方法,如下

    Paste_Image.png

    这种方法的缺陷是,分类的实现不能独立实现在一个分类文件中,必须实现在同一个文件中,局限性就很大了

    相关文章

      网友评论

          本文标题:【知识总结】category探索 — 如何在分类中添加一个属性(

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