分类(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)
}
}
}

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

1477

被折叠的 条评论
为什么被折叠?



