在我的项目中,我将错误提示页面的设置放在了一个类当中,方便其他页面的调用,但是这个页面有个用于重新加载的Button,我如何在其他的类为这个Button添加target呢?我想到了block的方式。接下来让我们看看如何实现。
在实现之前我们先了解一个两个方法
objc_setAssociatedObject(_:_:_:_:)
和objc_getAssociatedObject(_:_:)
这两个是runtime函数。对相关联的两个方法。
objc_setAssociatedObject(_:_:_:_:)
有四个参数
-
object
表示关联者,是一个对象,这里是UIButton(The source object for the association) -
key
被关联者的索引key,所以他是唯一的(The key for the association) -
value
被关联者,这里就是我们的block,如果这里传进来的是nil,那就表示断开关联(The value to associate with the key key for object. Pass nil to clear an existing association) -
policy
:关联策略。有五种关联策略。
OBJC_ASSOCIATION_ASSIGN
等价于@property(assign)
OBJC_ASSOCIATION_RETAIN_NONATOMIC
等价于@property(strong, nonatomic)
OBJC_ASSOCIATION_COPY_NONATOMIC
等价于@property(copy, nonatomic)
OBJC_ASSOCIATION_RETAIN
等价于@property(strong,atomic)
OBJC_ASSOCIATION_COPY
等价于@property(copy, atomic)
objc_getAssociatedObject(_:_:)
就顾名思义了,就是获取被关联者。它有两个参数。
-
object
和set方法一样,表示关联者(The source object for the association) -
key
被关联者的key(The key for the association)
我们所要做的就是将我们要传递的block关联到UIButton上去。
OK,准备完毕,接下来就是Coding的时候了。
首先,我们先来设置被关联者的key
var actionBlockKey: UInt8 = 0
声明我们的block,这个block就是我们要传进来的方法。
typealias BlockButtonActionBlock = (_ sender: UIButton) -> Void
接下来我们定义一个action的方法
class ActionBlockWrapper: NSObject {
var block: BlockButtonActionBlock
init(block: @escaping BlockButtonActionBlock) {
self.block = block
}
}
接下来就是关键的步骤,为UIButton添加扩展:
extension UIButton {
func block_setAction(block: @escaping BlockButtonActionBlock) {
objc_setAssociatedObject(self, &actionBlockKey, ActionBlockWrapper(block: block), objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
addTarget(self, action: #selector(UIButton.block_handleAction(sender:)), for: .touchUpInside)
}
func block_handleAction(sender: UIButton) {
if let wrapper = objc_getAssociatedObject(self, &actionBlockKey) as? ActionBlockWrapper {
wrapper.block(sender)
}
}
}
这里我们将我们传入的方法绑定到了UIButton的target上,就实现了,运用block为UIButton绑定target。我们在使用的时候,就不需要写addTarget方法,直接一个block搞定。
myButton.block_setAction { sender in
}
网友评论