Associated Object 添加属性(Swift篇)

本文介绍Swift中如何使用关联对象扩展类属性及按钮点击事件,通过objc_getAssociatedObject和objc_setAssociatedObject实现对类的无侵入式扩展,提供代码示例。

分类(category)与关联对象(Associated Object)作为objective-c的扩展机制的两个特性:分类,可以通过它来扩展方法;Associated Object,可以通过它来扩展属性;

在Swift中get和set Associated Object的API是这样的:

​
func objc_getAssociatedObject(object:AnyObject!,
                                key:UnsafePointer<Void>) -> AnyObject!

func objc_setAssociatedObject(object:AnyObject!,
                                key:UnsafePointer<Void>,
                                value:AnyObject!
                                policy:objc_AssociationPolicy)

​

示例1:

class Person {
}

extension Person {

    private struct AssociateKeys {
        static var key: Void?
    }

    var name: String? {
        get {
            return objc_getAssociatedObject(self, &AssociateKeys.key) as? String
        }

        set {
            objc_setAssociatedObject(self, &AssociateKeys.key, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
}

// 进行关联后,在对这个目标对象访问的时候,就像是直接在通过属性访问一样,非常方便
let p = Person()
p.name = "Zhangsan"
print(p.name!)

key的类型在这里声明为了Void?, 并且通过& 操作符取地址并作为UnsafePointer<Void>类型被传入,这在 Swift 与 C 协作和指针操作时是一种很常见的用法。

示例2:

扩展按钮的点击事件

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let btn: UIButton = UIButton(type: .contactAdd)
        btn.center = self.view.center
        btn.addAction(event: .touchUpInside) { (self) in      
            print("Button click") 
        }
        self.view.addSubview(btn)
    }

}

extension UIButton {

    private struct AssociateKeys {
        static var key: Void?
    }

    func addAction(event: Event, _ action: ((UIButton)->Void)?){
        // 通过objc_setAssociatedObject将闭包保存
        objc_setAssociatedObject(self, &AssociateKeys.key, action, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        addTarget(self, action: #selector(itemClick(button:)), for: event)

    }

    @objc private func itemClick(button: UIButton){
        // 点击按钮,通过objc_getAssociatedObject获取之前保存的闭包并调用
        if let block = objc_getAssociatedObject(self, &AssociateKeys.key) as? ((UIButton)->Void){
            block(button)
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值