Swift 在#selector 上传递参数

Swift passing parameter on #selector

如何使用相同的函数来处理 2 个不同文本字段上的 DatePickerView?

为了避免重复,我想设置 2 个带有 DatePicker 的文本字段。一个字段用于发布日期,另一个字段用于截止日期。

当我尝试在@objc func doneClick 上添加参数时,出现编译错误 ==> 实例成员 'doneClick' 不能用于类型 'InvoiceViewController';您是要改用这种类型的值吗?

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()
    }



}

doneClick 不能有 UITextField 类型的参数,当它用作 UIBarButtonItem.

的目标时

您需要编辑的不仅仅是那个方法。工具栏需要知道它属于哪个UITextField。因此,创建 UIToolbar 的自定义子类,您将在其中设置其项目,并向其添加一个委托,该委托将在完成和取消按下时发送事件:

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

现在使用此代码,您可以将旧代码重写为:

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