美文网首页
Swift 如何extension(拓展)存储属性

Swift 如何extension(拓展)存储属性

作者: 诗颜语 | 来源:发表于2022-03-30 14:53 被阅读0次

语法层面是不支持的,与OC一样通常使用关联对象实现
本文书写时Swift5.6

第一种

第一种就是static var修饰的变量加&,或者全局的 var 变量加&
通过这种方式添加的属性被拓展的类 不需要通过@objc修饰,不需要非得继承NSObject

class Test {
    
}
// or
// var testKey: String?
// var test1Key: String?
extension Test {
    private static var testKey = true
    
    var test: String {
        get {
            return objc_getAssociatedObject(self, &Self.testKey) as! String
        }
        set {
            objc_setAssociatedObject(self, &Self.testKey, newValue, .OBJC_ASSOCIATION_COPY)
        }
    }
    
    private static var test1Key = true
    
    var test1: String {
        get {
            return objc_getAssociatedObject(self, &Self.test1Key) as! String
        }
        set {
            objc_setAssociatedObject(self, &Self.test1Key, newValue, .OBJC_ASSOCIATION_COPY)
        }
    }
}
do {
    let obj = Test()
    obj.test = "123"
    obj.test1 = "789"
    print(obj.test)
    print(obj.test1)
}

do {
    let obj = Test()
    obj.test = "456"
    obj.test1 = "000"
    print(obj.test)
    print(obj.test1)
}

do {
    let obj = Test()
    obj.test = "999"
    obj.test1 = "555"
    print(obj.test)
    print(obj.test1)
}


第二种

通过selector当前属性的setter or getter 方法,相当于OC时的_cmd & @selector()
通过这种方式添加的属性 需要通过@objc修饰,因为#selector()只能包裹被@objc修饰的方法,不需要非得继承NSObject

extension NSObject {
    func setAssociated(key: Selector, value: Any?, policy: objc_AssociationPolicy) {
       let p = unsafeBitCast(key, to: UnsafeRawPointer.self)
       objc_setAssociatedObject(self, p, value, policy)
   }
   
   func getAssociated<T>(key: Selector) -> T? {
       let p = unsafeBitCast(key, to: UnsafeRawPointer.self)
       return objc_getAssociatedObject(self, p) as? T
   }
}

@objc extension NSObject {

    var test: String {
        get {
            getAssociated(key: #selector(setter: self.test)) ?? ""
        }
        set {
            setAssociated(key: #selector(setter: test), value: newValue, policy: .OBJC_ASSOCIATION_COPY_NONATOMIC)
        }
    }

    var test1: String {
        get {
            getAssociated(key: #selector(setter: self.test1)) ?? ""
        }
        set {
            setAssociated(key: #selector(setter: test1), value: newValue, policy: .OBJC_ASSOCIATION_COPY_NONATOMIC)
        }
    }
}


do {
    let obj = NSObject()
    obj.test = "123"
    obj.test1 = "789"
    print(obj.test)
    print(obj.test1)
}

do {
    let obj = NSObject()
    obj.test = "456"
    obj.test1 = "000"
    print(obj.test)
    print(obj.test1)
}

do {
    let obj = NSObject()
    obj.test = "999"
    obj.test1 = "555"
    print(obj.test)
    print(obj.test1)
}

do {
    let p = unsafeBitCast(#selector(setter: NSObject.test), to: UnsafeRawPointer.self)
    print(#function, p)
}
do {
    let p = unsafeBitCast(#selector(setter: NSObject.test), to: UnsafeRawPointer.self)
    print(#function, p)
}
do {
    let p = unsafeBitCast(#selector(setter: NSObject.test), to: UnsafeRawPointer.self)
    print(#function, p)
}
do {
    let p = unsafeBitCast(#selector(getter: NSObject.test), to: UnsafeRawPointer.self)
    print(#function, p)
}
do {
    let p = unsafeBitCast(#selector(setter: NSObject.test1), to: UnsafeRawPointer.self)
    print(#function, p)
}
do {
    let p = unsafeBitCast(#selector(getter: NSObject.test1), to: UnsafeRawPointer.self)
    print(#function, p)
}

第二种改进写法 - 利用协议

protocol AssociatedObject {}

extension AssociatedObject {
    func setAssociated(key: Selector, value: Any?, policy: objc_AssociationPolicy) {
       let p = unsafeBitCast(key, to: UnsafeRawPointer.self)
       objc_setAssociatedObject(self, p, value, policy)
   }
   
   func getAssociated<T>(key: Selector) -> T? {
       let p = unsafeBitCast(key, to: UnsafeRawPointer.self)
       return objc_getAssociatedObject(self, p) as? T
   }
}

class Test {}

@objc extension Test: AssociatedObject {

    var test: String {
        get {
            getAssociated(key: #selector(setter: self.test)) ?? ""
        }
        set {
            setAssociated(key: #selector(setter: test), value: newValue, policy: .OBJC_ASSOCIATION_COPY_NONATOMIC)
        }
    }

    var test1: String {
        get {
            getAssociated(key: #selector(setter: self.test1)) ?? ""
        }
        set {
            setAssociated(key: #selector(setter: test1), value: newValue, policy: .OBJC_ASSOCIATION_COPY_NONATOMIC)
        }
    }
}

相关文章

  • Swift 如何extension(拓展)存储属性

    语法层面是不支持的,与OC一样通常使用关联对象实现本文书写时Swift5.6 第一种 第一种就是static va...

  • 协议和扩展

    Swift Extension 添加存储属性 wift不允许在extension中直接添加「存储属性」。但是在我们...

  • iOS原理篇:关联对象

    前言 Swift中不能再extension中为类添加存储属性,如何利用关联对象变相添加属性呢? 关联对象相关API...

  • Swift Extension 添加存储属性

    Swift不允许在Extension中直接添加「存储属性」。但是在我们的实际开发中经常会用到使用Extension...

  • swift-类目添加属性

    Swift不允许在extension中直接添加「存储属性」。但是在我们的实际开发中经常会用到使用extension...

  • Swift如何借助Extension增加存储属性

    // 关联对象(Associated Object)// 在Swift中,class依然可以使用关联对象// ...

  • [Swift]为Extension添加存储属性

    众所周知, 在Swift的扩展(Extension)中只能添加计算属性, 但是有时候, 我们需要添加存储属性的话,...

  • 如何在Swift扩展中添加存储属性

    .一般而言,swift的扩展Extension只能添加计算属性,不能添加存储属性。当然,如果利用run time也...

  • Swift进阶(三)--- 属性

    Swift的属性 在swift中,属性主要分为以下几种: 存储属性 计算属性 延迟存储属性 类型属性 一:存储属性...

  • Swift 属性

    Swift 属性 在Swift中属性主要分为存储属性、计算属性、延迟存储属性、类型属性这四种,并且Swift还提供...

网友评论

      本文标题:Swift 如何extension(拓展)存储属性

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