将传递给方法的选择器分配为按钮目标操作

Assigning a selector passed to a method as a button target action

这是我的场景。我正在做吐司视图。 toast 视图接受一个选择器,它设置为 toast 视图内按钮的目标操作。但是我收到无法识别的选择器错误。

 // MainViewController.swift

 func viewDidLoad() {

     // Custom initializer for toastview
     let toastView = ToastView(view: nil, selector: #selector(testSelector))
     .
     .
     .
 }

 @objc func testSelector() {
      print("Test")
 }

 // ToastView.swift

 var selector: Selector

 convenience init(view: UIView, selector: Selector) {
      self.selector = selector
      let button = UIButton(type: .system)
      button.addTarget(self, action: self.selector, for: .touchUpInside)
 }

编辑:稍微更改了代码以反映我原始代码中的实际内容。

你弄错了目标。目标必须是定义选择器(方法或函数)的 class 的对象。如果在 MainViewController 中定义了函数,则目标必须是 MainViewController 的对象。如果函数在 ToastView 中定义,选择器必须是 ToastView 的对象,则相同。

要么将 testSelector 函数移动到 ToastView class 中,然后保持其余不变。

选项 1

// something like this 
class ToastView {
    @objc func testSelector() {
        print("Test")
    } 
}

选项 2

或者您将目标作为 init 参数传递。

// ToastView.swift
convenience init(view: UIView, target:Any, selector: Selector) {
    let button = UIButton(type: .system)
    button.addTarget(target, action: selector, for: .touchUpInside)
}

在你的 MainViewController 中这样称呼它。

func viewDidLoad() {

   // Custom initializer for toastview
   let toastView = ToastView(view: nil, target:self, selector: #selector(testSelector))
    .
    .
    .
}

不要传递选择器,而是根本不需要传递选择器。 按下按钮时触发通知,并将观察者添加到控制器的通知中。在与观察者

相关的那个选择器中做任何你想做的事情

如果您想执行 ToastView class 中的操作,您应该将 testSelector 移动到您的 ToastView class。

如果您想在 MainViewController 中执行操作,请使用自定义委托。

或者在ToastViewclass中全局声明button变量。然后您可以使用

MainViewController 中添加目标
let toastView = ToastView()
toastView.button.addTarget(target, action: selector, for: .touchUpInside)

您可以为按钮操作使用闭包而不是选择器

class ToastView: UIView {
    let button = UIButton()
    var btnAction:((Void) -> Void)?

    convenience init(_ btnAction: @escaping (Void) -> Void) {
        self.init()
        self.btnAction = btnAction
    }

    private init() {
        super.init(frame: .zero)
        button.addTarget(self, action: #selector(callbackButton(_:)), for: .touchUpInside)
    }

    func callbackButton(_ id:Any) -> Void {
        if self.btnAction != nil {
            self.btnAction!()
        }
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

在MainViewController.swift

func viewDidLoad() {

     // Custom initializer for toastview
     let toastView = ToastView.init( {(Void) -> Void in
        print("test")
    })
 }