【问题标题】:Swift passing parameter on #selector在#selector上快速传递参数
【发布时间】:2018-02-21 17:22:56
【问题描述】:

如何使用相同的函数来处理 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()
    }



}

【问题讨论】:

  • 不可能通过UIBarButtonItem 的动作选择器调用带有UITextField 参数的方法。操作方法必须有 UIBarButtonItem 参数或没有参数。
  • 我怎样才能对两个文本字段仅使用 1 个函数来实现呢?或者我不能,必须做 2 个功能?
  • 那你为什么用yyyy-MM-dd格式调用dateFormatter.string(from三次而不是一次?
  • 这 3 个电话是因为我还是 swift 新手。谢谢你的建议。
  • @RenanAguiar 我想它会帮助你stackoverflow.com/questions/43251708/…

标签: ios swift uidatepicker


【解决方案1】:

doneClick作为UIBarButtonItem的目标时,不能有UITextField类型的参数。

您将不得不编辑的不仅仅是那个方法。工具栏需要知道它属于哪个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)
    }
}

【讨论】:

  • 这样我不知道正在使用哪个文本字段。
  • @RenanAguiar 为什么你需要知道它? resigningFirstResponder 无论如何都会工作
  • 因为我有 2 个不同的字段(发布日期和截止日期)。就像现在一样,我可以在两个文本字段上打开选择器,但它只会更改发布日期,即使在截止日期打开也是如此
  • @RenanAguiar 为什么重要?您使用 textField 的唯一代码是在其上调用 resignFirstResponder 的代码。通过在两个 textField 上明确辞职,您将获得相同的行为..
  • 因为发行日期与到期日期不同。两种不同的数据。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-14
  • 1970-01-01
相关资源
最近更新 更多