为了账号安全,请及时绑定邮箱和手机立即绑定

有没有办法在Swift中设置关联对象?

有没有办法在Swift中设置关联对象?

月关宝盒 2019-10-16 14:12:27
来自目标C的您可以objc_setAssociatedObject在2个对象之间调用函数以使它们维护一个引用,如果在运行时您不希望在删除其引用之前也不要破坏某个对象的话,这会很方便。迅捷有与此类似的东西吗?
查看完整描述

3 回答

?
温温酱

TA贡献1752条经验 获得超4个赞

它显示了如何向现有类添加新属性。它通过在扩展块中定义计算属性来实现。计算的属性存储为关联的对象:


import ObjectiveC


// Declare a global var to produce a unique address as the assoc object handle

private var AssociatedObjectHandle: UInt8 = 0


extension MyClass {

    var stringProperty:String {

        get {

            return objc_getAssociatedObject(self, &AssociatedObjectHandle) as! String

        }

        set {

            objc_setAssociatedObject(self, &AssociatedObjectHandle, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)

        }

    }

}

编辑:


如果需要支持获取未初始化属性的值并避免发生错误unexpectedly found nil while unwrapping an Optional value,则可以按以下方式修改getter:


    get {

        return objc_getAssociatedObject(self, &AssociatedObjectHandle) as? String ?? ""

    }


查看完整回答
反对 回复 2019-10-16
?
小怪兽爱吃肉

TA贡献1852条经验 获得超1个赞

该解决方案还支持所有值类型,不仅支持自动桥接的值类型,例如String,Int,Double等。


包装纸


import ObjectiveC


final class Lifted<T> {

    let value: T

    init(_ x: T) {

        value = x

    }

}


private func lift<T>(x: T) -> Lifted<T>  {

    return Lifted(x)

}


func setAssociatedObject<T>(object: AnyObject, value: T, associativeKey: UnsafePointer<Void>, policy: objc_AssociationPolicy) {

    if let v: AnyObject = value as? AnyObject {

        objc_setAssociatedObject(object, associativeKey, v,  policy)

    }

    else {

        objc_setAssociatedObject(object, associativeKey, lift(value),  policy)

    }

}


func getAssociatedObject<T>(object: AnyObject, associativeKey: UnsafePointer<Void>) -> T? {

    if let v = objc_getAssociatedObject(object, associativeKey) as? T {

        return v

    }

    else if let v = objc_getAssociatedObject(object, associativeKey) as? Lifted<T> {

        return v.value

    }

    else {

        return nil

    }

}

可能的 Class扩展(用法示例)


extension UIView {


    private struct AssociatedKey {

        static var viewExtension = "viewExtension"

    }


    var referenceTransform: CGAffineTransform? {

        get {

            return getAssociatedObject(self, associativeKey: &AssociatedKey.viewExtension)

        }


        set {

            if let value = newValue {

                setAssociatedObject(self, value: value, associativeKey: &AssociatedKey.viewExtension, policy: objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)

            }

        }

    }

}


查看完整回答
反对 回复 2019-10-16
?
浮云间

TA贡献1829条经验 获得超4个赞

显然,这仅适用于Objective-C对象。经过一些摆弄之后,以下是在Swift中进行调用的方法:


import ObjectiveC


// Define a variable whose address we'll use as key.

// "let" doesn't work here.

var kSomeKey = "s"



func someFunc() {

    objc_setAssociatedObject(target, &kSomeKey, value, UInt(OBJC_ASSOCIATION_RETAIN))


    let value : AnyObject! = objc_getAssociatedObject(target, &kSomeKey)

}


查看完整回答
反对 回复 2019-10-16
  • 3 回答
  • 0 关注
  • 594 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信