如何将一个 pickerview 用于多个文本字段?

How to use one pickerview for multiple textfield?

我正在尝试构建一些东西(我是 Xcode 和 swift 的新手),我可以在其中从带有选择器视图的数组中选择一天的一餐,我希望我的选择显示在特定日期的文本字段中。我有这个工作,但只有 1 天。我怎样才能让这个相同的功能在所有(7)天内都有效?

我在单击下一个文本字段(星期二)时也设法获得了选择器视图,但是当我从列表中选择时,星期一的文本字段将遵循我在星期二所做的事情。它们是镜像的。我确实知道我应该做点什么来让那个 Tuesday-Picker 以某种方式变得独特,但这就是我卡住的地方。我不知道要做什么 change/write。任何人有任何想法?我在谷歌上搜索了一下,发现了很多关于选择器视图的信息,但没有找到如何以这种特定方式使用它们的信息...

//
//  ViewController.swift
//  dropdown
//
//  Created by -- on 2019-08-26.
//  Copyright © 2019 --. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

@IBOutlet weak var monday: UITextField!
@IBOutlet weak var tuesday: UITextField!
@IBOutlet weak var wednesday: UITextField!
@IBOutlet weak var thursday: UITextField!
@IBOutlet weak var friday: UITextField!
@IBOutlet weak var saturday: UITextField!
@IBOutlet weak var sunday: UITextField!

// the menu
let Menu = ["Palak Paner",
            "Spagetti Köttfärssås",
            "Thai Haloumi",
            "Thai Quorn",
            "Linssoppa",
            "SparrisPasta",
            "Gröt",
            "Gulasch"]

let tuesdayMenu = ["Palak Paner",
            "Spagetti Köttfärssås",
            "Thai Haloumi",
            "Thai Quorn",
            "Linssoppa",
            "SparrisPasta",
            "Gröt",
            "Gulasch"]


//When a menu from the list is selected, it will be shown as a string

var mondaySelectedMenu: String?
var tuesdaySelectedMenu: String?



override func viewDidLoad() {
    super.viewDidLoad()
    //Call on these functions when loaded
    createMondayMenuPicker()
    createTuesdayMenuPicker()
    createToolbar()
}

// This is the pickerView

func createMondayMenuPicker() {
    let mondayMenuPicker = UIPickerView()
    mondayMenuPicker.delegate = self
    monday.inputView = mondayMenuPicker
}

func createTuesdayMenuPicker() {
    let tuesdayMenuPicker = UIPickerView()
    tuesdayMenuPicker.delegate = self
    tuesday.inputView = tuesdayMenuPicker
}



// This is the "DONE" button
func createToolbar() {
    let toolBar = UIToolbar()
    toolBar.sizeToFit()

    let doneButton = UIBarButtonItem(title: "DONE", style: .plain, target: self, action: #selector(ViewController.dismissKeyboard))
    toolBar.setItems([doneButton], animated: false)
    toolBar.isUserInteractionEnabled = true

    monday.inputAccessoryView = toolBar
    tuesday.inputAccessoryView = toolBar
}


@objc func dismissKeyboard() {
    view.endEditing(true)

}

}


// This is the details for the pickerView
extension ViewController: UIPickerViewDelegate, UIPickerViewDataSource {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
    return 1
}

func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    return Menu.count
}


func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
    return Menu[row]
}

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {

    mondaySelectedMenu = Menu[row]
    tuesdaySelectedMenu = tuesdayMenu[row]
    monday.text = mondaySelectedMenu
    tuesday.text = tuesdaySelectedMenu
}



}

所以,我想在点击所有 7 天时调用同一个数组,但我想显示从该列表中选择的每一天的独特选择。有任何想法吗?非常感谢!

实现此目的的一种方法是使用以下方法。我已经将工具栏功能分离到它自己的 class.

创建一个新的 class pickerview 工具栏(在本例中我调用了 ToolbarPickerView.swift)

import UIKit

protocol ToolbarPickerViewDelegate: class {
    func didTapDone()
    func didTapCancel()
}

class ToolbarPickerView: UIPickerView {

    public private(set) var toolbar: UIToolbar?
    public weak var toolbarDelegate: ToolbarPickerViewDelegate?

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.commonInit()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.commonInit()
    }

    private func commonInit() {
        let toolBar = UIToolbar()
        toolBar.barStyle = UIBarStyle.default
        toolBar.isTranslucent = true
        toolBar.tintColor = .black
        toolBar.sizeToFit()

        let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(self.doneTapped))
        let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
        let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(self.cancelTapped))

        toolBar.setItems([cancelButton, spaceButton, doneButton], animated: false)
        toolBar.isUserInteractionEnabled = true

        self.toolbar = toolBar
    }

    @objc func doneTapped() {
        self.toolbarDelegate?.didTapDone()
    }

    @objc func cancelTapped() {
        self.toolbarDelegate?.didTapCancel()
    }
}

在ViewController

import UIKit
class ViewController: UIViewController {

    @IBOutlet weak var monday: UITextField!
    @IBOutlet weak var tuesday: UITextField!
    @IBOutlet weak var wednesday: UITextField!
    @IBOutlet weak var thursday: UITextField!
    @IBOutlet weak var friday: UITextField!
    @IBOutlet weak var saturday: UITextField!
    @IBOutlet weak var sunday: UITextField!

    var daysArray = [UITextField]()

    let pickerView = ToolbarPickerView()

    let Menu = ["Palak Paner",
                "Spagetti Köttfärssås",
                "Thai Haloumi",
                "Thai Quorn",
                "Linssoppa",
                "SparrisPasta",
                "Gröt",
                "Gulasch"]

    var selectedMenu : String?

    override func viewDidLoad() {
        super.viewDidLoad()

        setupDelegateForPickerView()
        setupDelegatesForTextFields()
    }

    func setupDelegatesForTextFields() {
        //appending textfields in an array
        daysArray += [monday, tuesday, wednesday, thursday, friday, saturday, sunday]
        //using the array to set up the delegates, inputview for pickerview and also the inputAccessoryView for the toolbar
        for day in daysArray {
            day.delegate = self
            day.inputView = pickerView
            day.inputAccessoryView = pickerView.toolbar
        }
    }

    func setupDelegateForPickerView() {
        pickerView.dataSource = self
        pickerView.delegate = self
        pickerView.toolbarDelegate = self
    }
}

为文本字段委托创建扩展

extension ViewController : UITextFieldDelegate {
    func textFieldDidBeginEditing(_ textField: UITextField) {
        self.pickerView.reloadAllComponents()
    }
}

pickerview 和工具栏的扩展

extension ViewController : UIPickerViewDelegate, UIPickerViewDataSource {
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return self.Menu.count
    }

    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return self.Menu[row]
    }

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        // Check if the textfield isFirstResponder.
        if monday.isFirstResponder {
            monday.text = self.Menu[row]
        } else if tuesday.isFirstResponder {
            tuesday.text = self.Menu[row]
        } else if wednesday.isFirstResponder {
            wednesday.text = self.Menu[row]
        } else if thursday.isFirstResponder {
            thursday.text = self.Menu[row]
        } else if friday.isFirstResponder {
            friday.text = self.Menu[row]
        } else if saturday.isFirstResponder {
            saturday.text = self.Menu[row]
        } else if sunday.isFirstResponder {
            sunday.text = self.Menu[row]
        } else {
        //log errors
        }
    }
}

extension ViewController: ToolbarPickerViewDelegate {

    func didTapDone() {
//      let row = self.pickerView.selectedRow(inComponent: 0)
//      self.pickerView.selectRow(row, inComponent: 0, animated: false)
//      selectedMenu = self.Menu[row]
        self.view.endEditing(true)
    }

    func didTapCancel() {
       self.view.endEditing(true)
    }
}

PickerView的didSelectRow函数改成下面可以简化

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {

        for day in daysArray {
            if day.isFirstResponder {
                day.text = self.Menu[row]
            }
        }
    }

希望这个回答对您有所帮助。

创建一个通用选择器 class,如下所示:

class PKMultiPicker: UIPickerView, UIPickerViewDelegate, UIPickerViewDataSource {

internal typealias PickerDone = (_ firstValue: String, _ secondValue: String) -> Void
private var doneBlock : PickerDone!

private var firstValueArray : [String]?
private var secondValueArray = [String]()
static var noOfComponent = 2


class func openMultiPickerIn(_ textField: UITextField? , firstComponentArray: [String], secondComponentArray: [String], firstComponent: String?, secondComponent: String?, titles: [String]?, toolBarTint: UIColor = UIColor.black, doneBlock: @escaping PickerDone) {

    let picker = PKMultiPicker()
    picker.doneBlock = doneBlock

    picker.openPickerInTextField(textField, firstComponentArray: firstComponentArray, secondComponentArray: secondComponentArray, firstComponent: firstComponent, secondComponent: secondComponent, toolBarTint: toolBarTint)

    if titles != nil {
        let label = UILabel(frame: CGRect(x: UIScreen.main.bounds.size.width/4 - 10, y: 0, width: 100, height: 30))
        label.text = titles![0].uppercased()
        label.font = UIFont.boldSystemFont(ofSize: 18)
        picker.addSubview(label)

        if PKMultiPicker.noOfComponent > 1 {
            let label = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 30))
            label.text = titles![1].uppercased()
            label.font = UIFont.boldSystemFont(ofSize: 18)
            picker.addSubview(label)
        } else {
            label.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 30)
            label.textAlignment = NSTextAlignment.center
        }
    }
}

private func openPickerInTextField(_ textField: UITextField?, firstComponentArray: [String], secondComponentArray: [String], firstComponent: String?, secondComponent: String?, toolBarTint: UIColor = UIColor.black) {

    firstValueArray  = firstComponentArray
    secondValueArray = secondComponentArray

    self.delegate = self
    self.dataSource = self


    let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(pickerCancelButtonTapped))
    cancelButton.tintColor = toolBarTint
    let doneButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.done, target: self, action: #selector(pickerDoneButtonTapped))
    doneButton.tintColor = toolBarTint
    let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action:nil)

    let toolbar = UIToolbar()
    toolbar.sizeToFit()
    let array = [cancelButton, spaceButton, doneButton]
    toolbar.setItems(array, animated: true)
    toolbar.backgroundColor = UIColor.lightText

    textField?.inputView = self
    textField?.inputAccessoryView = toolbar

    let index = self.firstValueArray?.index(where: {[=10=].lowercased() == (firstComponent ?? "").lowercased() })
    self.selectRow(index ?? 0, inComponent: 0, animated: true)


    if PKMultiPicker.noOfComponent > 1 {
        let index1 = self.secondValueArray.index(where: {[=10=].lowercased() == (secondComponent ?? "").lowercased() })
        self.selectRow(index1 ?? 0, inComponent: 1, animated: true)
    }
}

@IBAction private func pickerCancelButtonTapped(){
    UIApplication.shared.keyWindow?.endEditing(true)
}

@IBAction private func pickerDoneButtonTapped(){

    UIApplication.shared.keyWindow?.endEditing(true)

    let index1 : Int?
    let firstValue : String?
    index1 = self.selectedRow(inComponent: 0)

    if firstValueArray?.count == 0{return}
    else{firstValue = firstValueArray?[index1!]}

    var index2 :Int!
    var secondValue: String!
    if PKMultiPicker.noOfComponent > 1 {
        index2 = self.selectedRow(inComponent: 1)
        secondValue = secondValueArray[index2]
    }
    self.doneBlock((firstValue ?? ""), (secondValue ?? ""))
}

func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {

    if component == 0 {
        return firstValueArray!.count
    }
    return secondValueArray.count
}

func numberOfComponents(in pickerView: UIPickerView) -> Int {
    return PKMultiPicker.noOfComponent
}


func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {

    switch component {

    case 0:
        return firstValueArray?[row]
    case 1:
        return secondValueArray[row]
    default:
        return ""
    }
}
}

示例代码 打开选择器并管理选择,还有更多选项,您还可以管理组件数量:-

  PKMultiPicker.noOfComponent = 1
  PKMultiPicker.openMultiPickerIn(textField, firstComponentArray: ["Apple", "Mango","Grapes","Pine apple"], secondComponentArray: [], firstComponent: textField.text, secondComponent: nil, titles: nil, toolBarTint: AppColors.themeGreen) { (firstSelect, secondSelect) in
                        print("first select : \(firstSelect)")
                        textField.text = firstSelect // you can set text here to the respective text field.

                    }

此处 @pawan_kumar 描述了一种对具有相同数据的多个文本字段使用相同选择器视图的方法。但您也可以为此绑定不同的数据源。 有一个示例代码。在这里,我使用 UITextField.isFirstResponder 来决定应该将哪些数据加载到选择器视图中。希望这个回答对你也有帮助。