Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/119.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 将选择器作为按钮目标操作传递给方法_Ios_Swift_Unrecognized Selector - Fatal编程技术网

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

Ios 将选择器作为按钮目标操作传递给方法,ios,swift,unrecognized-selector,Ios,Swift,Unrecognized Selector,这是我的设想。我要举杯庆祝。toast视图接受一个选择器,它将该选择器设置为toast视图中按钮的目标操作。但我得到了无法识别的选择器错误 // MainViewController.swift func viewDidLoad() { // Custom initializer for toastview let toastView = ToastView(view: nil, selector: #selector(testSelector)) .

这是我的设想。我要举杯庆祝。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)
 }

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

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

或者将
类中的
testSelector
函数移动到stview
类中,并保持其余部分不变

选项1

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

或者将目标作为
init
paramater传递

// 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))
    .
    .
    .
}

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

或者将
类中的
testSelector
函数移动到stview
类中,并保持其余部分不变

选项1

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

或者将目标作为
init
paramater传递

// 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
类中执行操作,则应将
testSelector
移动到
ToastView
类中

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

或者在
ToastView
类中全局声明
按钮
变量。然后,您可以使用在
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")
    })
 }

如果要在
ToastView
类中执行操作,应将
testSelector
移动到
ToastView

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

或者在
ToastView
类中全局声明
按钮
变量。然后,您可以使用在
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")
    })
 }


谢谢你的选择。但是添加一个观察者会给这样一个微小的特性增加开销。难道没有办法通过选择器让它工作吗?为什么?传递选择器将推断在toast的初始化过程中传递不同的方法,这意味着不同的控制器使用不同的方法。这里基本上是一样的。或者你也可以使用委托,但将选择器从控制器传递到视图基本上会带来麻烦。使用按钮按下通知几乎从来都不是解决方案。正如我所说的,这是一种观点,你也可以使用委托,但在我看来,使用按钮动作通知是比传递选择器更好的解决方案,另外,如果您决定传递选择器,请检查toast视图的deinit是否被调用,因为它可能会保留一些值,并且retain count可能永远不会达到0。但是添加一个观察者会给这样一个微小的特性增加开销。难道没有办法通过选择器让它工作吗?为什么?传递选择器将推断在toast的初始化过程中传递不同的方法,这意味着不同的控制器使用不同的方法。这里基本上是一样的。或者你也可以使用委托,但将选择器从控制器传递到视图基本上会带来麻烦。使用按钮按下通知几乎从来都不是解决方案。正如我所说的,这是一种观点,你也可以使用委托,但在我看来,使用按钮动作通知是比传递选择器更好的解决方案,另外,如果您决定传递选择器,请检查toast视图的deinit是否被调用,因为它可能会保留一些值,并且retain count可能永远不会达到0。button.addTarget(toast,selector:toast.selector,for:.touchUpInside)仍然存在相同的问题。您如何称呼它?将目标作为自身传递?否。将其更改为保留选择器的位置。(ToastView的例子)真的很抱歉。为了更好地反映我的实际用例,对问题做了一些修改。目标必须是定义选择器的地方。它是在viewcontriller中定义的,所以目标应该是self。将目标和选择器都传递给init是更好的解决方案。尝试了这个方法。button.addTarget(toast,selector:toast.selector,for:.touchUpInside)仍然存在相同的问题。您如何称呼它?将目标作为自身传递?否。将其更改为保留选择器的位置。(ToastView的例子)真的很抱歉。为了更好地反映我的实际用例,对问题做了一些修改。目标必须是定义选择器的地方。它在ViewController中定义,所以目标应该是self。传递两个ta