使用闭包作为按钮的动作

时间:2019-12-11 06:58:55

标签: ios swift closures

背景

我必须在我的整个应用中创建一些日期时间选择器,因此我在考虑创建一个 Utility 类,该类将返回可重复使用的UIDateTimePicker我将在整个应用程序中使用。每个选择器在工具栏

中都有一个取消完成按钮

问题 对于点击 Cancel Done 时应该执行的操作,我正在考虑使用如下闭包:

func createDatePicker(isDateTime: Bool, doneAction: ()->(), cancelAction: ()->()) -> UIDatePicker {

    // Code for setting up the dateTime picker

    // Deciding the picker mode for the picker
    dateTimePicker.datePickerMode = isDateTime ? UIDatePicker.Mode.dateAndTime : UIDatePicker.Mode.date

    // Creating a toolbar for the Picker

    let toolbar = UIToolbar()
    toolbar.sizeToFit()

    // Creating buttons for toolbar
    let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.done, target: self, action: #selector(doneAction)) // ---- ERROR -----

    let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)

    let cancelButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.plain, target: self, action: #selector(cancelAction)) // ---- ERROR -----

    // Adding buttons to the toolbar
    toolbar.setItems([cancelButton,spaceButton,doneButton], animated: false)

    // Adding the Toolbar to the dateTimePicker and returning the dateTimePicker

}

现在,当我尝试将闭包添加为按钮操作时,会出现问题,因为它们不是选择器(附加了@objc

我得到的错误是

  

“#selector”的参数不能引用参数“ doneAction”

如何解决此问题,或有另一种方法将要执行的代码(在“取消并完成”时)从main(ViewController)类传递到此实用工具类

3 个答案:

答案 0 :(得分:2)

如果我对您的理解正确,则可以通过将委托添加到班级来解决此问题。这是一些如何做的例子。希望对您有帮助

    protocol DoneCancelAction {

    func doneAction()
    func cancelAction()

}

class DateTimePicker: UIDatePicker {

    var dateTimePicker: DateTimePicker!
    var delegate: DoneCancelAction? = nil

    func createDatePicker(isDateTime: Bool) -> UIDatePicker {

        // Code for setting up the dateTime picker

        // Deciding the picker mode for the picker
        dateTimePicker.datePickerMode = isDateTime ? UIDatePicker.Mode.dateAndTime : UIDatePicker.Mode.date

        // Creating a toolbar for the Picker

        let toolbar = UIToolbar()
        toolbar.sizeToFit()

        // Creating buttons for toolbar
        let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItem.Style.done, target: self, action: #selector(doneAction)) // ---- ERROR -----

        let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil)

        let cancelButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItem.Style.plain, target: self, action: #selector(cancelAction)) // ---- ERROR -----

        // Adding buttons to the toolbar
        toolbar.setItems([cancelButton,spaceButton,doneButton], animated: false)

        // Adding the Toolbar to the dateTimePicker and returning the dateTimePicker


        return dateTimePicker

    }

    @objc func doneAction() {
        delegate?.doneAction()
    }

    @objc func cancelAction() {
        delegate?.cancelAction()
    }

}

class MyVC: UIViewController, DoneCancelAction {

    var dateTimePicker: DateTimePicker!

    override func viewDidLoad() {
        super.viewDidLoad()
        dateTimePicker.delegate = self
    }

    func doneAction() {
        // your code
    }

    func cancelAction() {
        // your code
    }

}

答案 1 :(得分:1)

1。正确的方法是使用协议,只需使DateTypeProtocol向其添加提交按钮和取消按钮操作功能即可。

2。在实用工具类上创建单独的函数,并使用委托调用协议函数

3。然后在使用它时让使用它的类遵守协议并在那里执行操作。

答案 2 :(得分:1)

class Closure {
    let closure: ()->()

    init (_ closure: @escaping ()->()) {
        self.closure = closure
    }

    @objc func action () {
        closure()
    }
}

extension UIBarButtonItem {
    public convenience init(title: String?, style: UIBarButtonItem.Style, action: @escaping ()->()) {
        let handle = Closure(action)
        self.init(title: title, style: style, target: handle, action: #selector(Closure.action))
        objc_setAssociatedObject(self, "ex_action", handle, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
    }
}
let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItem.Style.done, action: doneAction)