Swift passing parameter on #selector

ぃ、小莉子 提交于 2019-12-24 20:52:13

问题


How can I use the same function to handle DatePickerView on 2 different textFields?

To avoid repetition, I would like to set up 2 textFields with a DatePicker. One field is for issue date and the other one for due date.

When I try to add parameter on @objc func doneClick, I got a compiler error ==> Instance member 'doneClick' cannot be used on type 'InvoiceViewController'; did you mean to use a value of this type instead?

import UIKit

class InvoiceViewController: UIViewController, UITextFieldDelegate{

    var thePicker = UIDatePicker()

    @IBOutlet weak var dateIssueTextField: UITextField!
    @IBOutlet weak var dueDateTextField: UITextField!

    @objc func doneClick(textField: UITextField!) {
        let dateFormatter = DateFormatter()
        dateFormatter.dateStyle = .short
        dateFormatter.timeStyle = .none
        dateIssueTextField.text = dateFormatter.string(from: thePicker.date)

        dateFormatter.dateFormat = "yyyy"
        let year: String = dateFormatter.string(from: self.thePicker.date)
        dateFormatter.dateFormat = "MM"
        let month: String = dateFormatter.string(from: self.thePicker.date)
        dateFormatter.dateFormat = "dd"
        let day: String = dateFormatter.string(from: self.thePicker.date)

        let finalDate = year+"-"+month+"-"+day
        print(finalDate)
       // dateIssueTextField.resignFirstResponder()
        textField.resignFirstResponder()
    }

    @objc func cancelClick() {
        dateIssueTextField.resignFirstResponder()
    }

    func setUpTextFieldPicker(textField: UITextField) {
        // DatePicker
        self.thePicker = UIDatePicker(frame:CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 216))
        self.thePicker.backgroundColor = UIColor.white
        self.thePicker.datePickerMode = UIDatePickerMode.date
       // dateIssueTextField.inputView = thePicker
       // dueDateTextField.inputView = thePicker
        textField.inputView = thePicker

        // ToolBar
        let toolBar = UIToolbar()
        toolBar.barStyle = .default
        toolBar.isTranslucent = true
        toolBar.tintColor = UIColor(red: 92/255, green: 216/255, blue: 255/255, alpha: 1)
        toolBar.sizeToFit()

        // Adding Button ToolBar
        let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(InvoiceViewController.doneClick))
        let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
        let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(InvoiceViewController.cancelClick))
        toolBar.setItems([cancelButton, spaceButton, doneButton], animated: false)
        toolBar.isUserInteractionEnabled = true
        //dateIssueTextField.inputAccessoryView = toolBar
        //dueDateTextField.inputAccessoryView = toolBar
        textField.inputAccessoryView = toolBar
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        setUpTextFieldPicker(textField: dateIssueTextField)
        setUpTextFieldPicker(textField: dueDateTextField)

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }



}

回答1:


doneClick cannot have parameter of UITextField type, when it's used as a target to UIBarButtonItem.

You will have to edit more than just that method. The toolbar needs to know to which UITextField it belongs to. So create your custom subclass of UIToolbar, in which you will setup its items, and add a delegate to it which will be sent events on done and cancel pressed:

import UIKit

protocol AccessoryToolbarDelegate: class {
    func doneClicked(for textField: UITextField)
    func cancelClicked(for textField: UITextField)
}

class AccessoryToolbar: UIToolbar {

    fileprivate let textField: UITextField

    weak var accessoryDelegate: AccessoryToolbarDelegate?

    init(for textField: UITextField) {
        self.textField = textField
        super.init(frame: CGRect.zero)

        self.barStyle = .default
        self.isTranslucent = true
        self.tintColor = UIColor(red: 92/255, green: 216/255, blue: 255/255, alpha: 1)
        self.sizeToFit()

        let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(doneClicked))
        let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
        let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(cancelClicked))
        self.setItems([cancelButton, spaceButton, doneButton], animated: false)
        self.isUserInteractionEnabled = true

        textField.inputAccessoryView = self
    }

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

    @objc fileprivate func doneClicked() {
        accessoryDelegate?.doneClicked(for: self.textField)
    }

    @objc fileprivate func cancelClicked() {
        accessoryDelegate?.cancelClicked(for: self.textField)
    }
}

Now with this code you can rewrite your old code to:

import UIKit

class InvoiceViewController: UIViewController, AccessoryToolbarDelegate {
    var thePicker = UIDatePicker()

    @IBOutlet weak var dateIssueTextField: UITextField!
    @IBOutlet weak var dueDateTextField: UITextField!

    func doneClicked(for textField: UITextField) {
        let dateFormatter = DateFormatter()
        dateFormatter.dateStyle = .short
        dateFormatter.timeStyle = .none
        // I am not sure if you want this
        textField.text = dateFormatter.string(from: thePicker.date)

        // or rather this, but that's up to you to finish
        dateFormatter.dateFormat = "yyyy-MM-dd"
        let finalDate: String = dateFormatter.string(from: thePicker.date)
        print(finalDate)

        textField.resignFirstResponder()
    }

    func cancelClicked(for textField: UITextField) {
        textField.resignFirstResponder()
    }

    func setUpTextFieldPicker(textField: UITextField) {
        // DatePicker
        self.thePicker = UIDatePicker(frame:CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 216))
        self.thePicker.backgroundColor = UIColor.white
        self.thePicker.datePickerMode = UIDatePickerMode.date
        // dateIssueTextField.inputView = thePicker
        // dueDateTextField.inputView = thePicker
        textField.inputView = thePicker

        // ToolBar
        let toolbar = AccessoryToolbar(for: textField)
        // let's not forget to set the delegate
        toolbar.accessoryDelegate = self
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        setUpTextFieldPicker(textField: dateIssueTextField)
        setUpTextFieldPicker(textField: dueDateTextField)
    }
}


来源:https://stackoverflow.com/questions/48911916/swift-passing-parameter-on-selector

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!