用block的方式为UIButton添加target

在我的项目中,我将错误提示页面的设置放在了一个类当中,方便其他页面的调用,但是这个页面有个用于重新加载的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
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容