带有按钮和选择器的协议扩展
Protocol extension with button and selector
我有一些协议:
@objc protocol SomeProtocol { }
我扩展了 UIViewController
个实例。在此扩展中,我想创建并添加一个按钮,其选择器也在协议中定义:
extension SomeProtocol where Self: UIViewController {
func addSomeButton() {
let someButton = UIButton()
someButton.addTarget(self, #selector(someButtonPressed), for: .touchUpInside)
view.addSubview(someButton)
}
@objc func someButtonPressed() {
}
}
但是,我收到错误 @objc can only be used with members of 类、@objc protocols 和 类 的具体扩展someButtonPressed
.
的定义
有什么方法可以使用协议来实现吗?
提前感谢您的任何建议!
您需要在协议中提供 Selector
要求。这是因为您只能将 @objc
属性应用于 NSObject
。标记协议 @objc
的唯一原因是为了可选方法。
@objc protocol SomeProtocol {
var action: Selector { get }
}
将扩展名更改为:
extension SomeProtocol where Self: UIViewController {
func addSomeButton() {
let someButton = UIButton()
someButton.addTarget(self, action: action, for: .touchUpInside)
view.addSubview(someButton)
}
}
现在,这有效:
extension UIViewController: SomeProtocol {
@objc func buttonPressed(sender: UIButton) {
print("Button pressed")
}
var action: Selector {
return #selector(buttonPressed(sender:))
}
}
用法:
let vc: myViewController: MyViewController!
func doSomething() {
vc.addSomeButton()
}
一种解决方法是向 UIButton
添加一个封闭套管而不是此处显示的目标操作 并为方便起见复制在下面。
typealias Closure = () -> ()
///
class ClosureSleeve {
let closure: Closure
init(_ closure: @escaping Closure) {
self.closure = closure
}
@objc func invoke () {
closure()
}
}
extension UIControl {
func addAction(for controlEvents: UIControl.Event = .touchUpInside, _ closure: @escaping Closure) {
let sleeve = ClosureSleeve(closure)
addTarget(sleeve, action: #selector(ClosureSleeve.invoke), for: controlEvents)
objc_setAssociatedObject(self, String(format: "[%d]", arc4random()), sleeve, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
}
}
然后简单地替换:
someButton.addTarget(self, #selector(someButtonPressed), for: .touchUpInside)
与:
someButton.addAction { [weak self] in
self?.someButtonPressed()
}
嘿嘿。
我有一些协议:
@objc protocol SomeProtocol { }
我扩展了 UIViewController
个实例。在此扩展中,我想创建并添加一个按钮,其选择器也在协议中定义:
extension SomeProtocol where Self: UIViewController {
func addSomeButton() {
let someButton = UIButton()
someButton.addTarget(self, #selector(someButtonPressed), for: .touchUpInside)
view.addSubview(someButton)
}
@objc func someButtonPressed() {
}
}
但是,我收到错误 @objc can only be used with members of 类、@objc protocols 和 类 的具体扩展someButtonPressed
.
有什么方法可以使用协议来实现吗?
提前感谢您的任何建议!
您需要在协议中提供 Selector
要求。这是因为您只能将 @objc
属性应用于 NSObject
。标记协议 @objc
的唯一原因是为了可选方法。
@objc protocol SomeProtocol {
var action: Selector { get }
}
将扩展名更改为:
extension SomeProtocol where Self: UIViewController {
func addSomeButton() {
let someButton = UIButton()
someButton.addTarget(self, action: action, for: .touchUpInside)
view.addSubview(someButton)
}
}
现在,这有效:
extension UIViewController: SomeProtocol {
@objc func buttonPressed(sender: UIButton) {
print("Button pressed")
}
var action: Selector {
return #selector(buttonPressed(sender:))
}
}
用法:
let vc: myViewController: MyViewController!
func doSomething() {
vc.addSomeButton()
}
一种解决方法是向 UIButton
添加一个封闭套管而不是此处显示的目标操作 并为方便起见复制在下面。
typealias Closure = () -> ()
///
class ClosureSleeve {
let closure: Closure
init(_ closure: @escaping Closure) {
self.closure = closure
}
@objc func invoke () {
closure()
}
}
extension UIControl {
func addAction(for controlEvents: UIControl.Event = .touchUpInside, _ closure: @escaping Closure) {
let sleeve = ClosureSleeve(closure)
addTarget(sleeve, action: #selector(ClosureSleeve.invoke), for: controlEvents)
objc_setAssociatedObject(self, String(format: "[%d]", arc4random()), sleeve, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
}
}
然后简单地替换:
someButton.addTarget(self, #selector(someButtonPressed), for: .touchUpInside)
与:
someButton.addAction { [weak self] in
self?.someButtonPressed()
}
嘿嘿。