美文网首页
iOS 关联对象

iOS 关联对象

作者: 一滴矿泉水 | 来源:发表于2022-02-22 20:46 被阅读0次

    可以给Category(或者 Swift中类的拓展)添加成员变量么?

    这是一个经典的面试题. 通过源码, 我们可以很直观的看到, 分类的结构体 category_t 并没有 ivas 成员变量, 所以我们不可以直接给Category 添加成员变量

    但是 category_t 中有 属性列表 properties, 那么也就是说可以给属性添加属性, 但是这跟本来的属性有什么区别呢?

    本类中的属性, 编译器会自动帮我们生成setter和getter方法, 但是Category中的属性并不会, 所以当在Category我们声明了一个属性, 在给属性赋值时, 就会报错。

    所以, 这就需要我们自己手动给分类的属性添加setter和getter方法. 但是分类又不能添加成员变量, 那么我们的setter方法给谁赋值? getter 又返回谁? 下面我们以Swift 类拓展添加关联对象做举例。

    关联对象技术

    我们可以通过关联对象间接给一个Swift的类拓展添加一个类似成员变量的东西. 关联对象相关有三个主要的函数

    /** 给一个对象设置关联对象
    object: 需要添加关联的源对象
    key: 关联值的唯一key
    value: 关联的具体值
    policy: 关联的策略 (类似声明properties的参数)
    */
    void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
    
    /** 获取某个对象的某个关联对象
    object: 需要获取关联的源对象
    key: 关联值的唯一key
    */
    id objc_getAssociatedObject(id object, const void *key)
    
    /** 移除对象的关联对象
     object: 需要移除的源对象
    */
    void objc_removeAssociatedObjects(id object) 
    

    通过关联对象技术, 我们可以在setter方法中, 给 cName 赋值, 在getter方法中获取 cName 的值

    代码举例(给UIButton的拓展添加一个count属性)

    extension UIButton {
        private static var ADJ_KEY: Void?
        var count: Int {
            get {
                (objc_getAssociatedObject(self, &Self.ADJ_KEY) as? Int) ?? 0
            }
            set {
                objc_setAssociatedObject(self, &Self.ADJ_KEY, newValue,     .OBJC_ASSOCIATION_COPY)
            }
        }
    }
    

    使用

    override func viewDidLoad() {
        super.viewDidLoad()
        let test = UIButton()
        test.count = 200
        print(test.count)
    }
    

    文章持续更新中、希望对各位有所帮助、有问题可留言 大家共同学习.

    相关文章

      网友评论

          本文标题:iOS 关联对象

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