美文网首页
Swift Associated Object

Swift Associated Object

作者: 吕建雄 | 来源:发表于2021-08-23 14:50 被阅读0次

Swift中Associated Object使用

使用关联对象在扩展中增加实例字段。

需要定义一个本地变量(private var key: UInt8)用来取地址。

Swift Extension比Objective-C Category增色不少,extension能够给已有类添加计算型属性,但是仍不能添加存储属性。Swift中可以使用Objective-C的关联对象(Associated Objects)的方式添加属性,弥补这一痛点

Swift中提供3个与Objective-C类似的方法将自定义属性关联到对象上:

1、objc_setAssociatedObject

2、objc_getAssociatedObject

3、objc_removeAssociatedObjects

需要注意的是:objc_removeAssociatedObjects会删除对象关联的所有属性,所以可能导致把一些非自己添加的关联属性也删除掉。如果要删除某属性,使用objc_setAssociatedObject将value设置为nil即可

抽取关联对象方法

可以把关联对象的方法提取成公共方法,在NSObject类的extension里实现,只要继承子NSObject的类就能够调用关联对象方法,通过Swift泛型来关联不同类型的属性

extension NSObject{

    func setAssociated(value: T, associatedKey: UnsafeRawPointer, policy:     objc_AssociationPolicy =     objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) -> Void{

        objc_setAssociatedObject(self, associatedKey, value, policy)

}

    func getAssociated(associatedKey: UnsafeRawPointer) -> T? {

        return objc_getAssociatedObject(self, associatedKey) as? T

    }

}

在Swift中使用objc_setAssociatedObject和objc_getAssociatedObject时,调用setAssociated或getAssociated即可

extension UIView{

    private struct AssociatedKeys{

        static var displayName = “dispalyNameKey”

    }

    var displayName: String? {

        get{

            return getAssociated(associatedKey: &AssociatedKeys.displayNameKey)

        }

        set{

            setAssociated(value: newValue, associatedKey: &AssociatedKeys.displayNameKey, policy: objc_AssociationPolicy.OBJC_ASSOCIATION_COPY_NONATOMIC)

        }

    }

}

在使用Swift Associated Object中需要注意的是:

1、嵌套私有结构体,声明与扩展属性对应的键(key),Swift Extension提供了丰富的功能,可以在Extension中嵌套类型,使用private私有访问控制,不会污染整个命名空间,而且能够统一管理关联对象键

2、Swift的基本类型Int,Float,Double,Bool能够自动隐式地转换成Objective-C的NSNumber,所以不需要显式的包装成NSNumber类型进行关联

3、如果使用OBJC_ASSOCIATION_ASSIGN关联策略时需要注意,文档中指出是弱引用,但不完全等同于weak,更像是unsafe_unretained引用,关联对象被释放后,关联属性仍然保留被释放的地址,如果不小心访问关联属性,就会造成野指针访问出错。

如果使用Associted Object关联闭包属性,则需要创建闭包容器

分以下两个步骤:

1、在extension中嵌套创建容器类,容器类中定义需要关联的闭包属性

2、关联对象时把容器类对象关联到已有类,间接的就把闭包属性关联到一有类

typealisa completionClosure = ()->()

extension  UIViewController{

    private struct AssociatedKeys {

        static var completionKey = “completionKey”

    }

    class Container {

        var completion: completionClosure?

    }

    var container: Container?{

        get{

            return objc_getAssociatedObject(self, &AssociatedKeys.completionKey)

        }

        set{

            objc_setAssociatedObject(self, &AssociatedKeys.completionKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONTOMIC)

        }

    }

}

相关文章

网友评论

      本文标题:Swift Associated Object

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