问题
I currently have a view controller with 3 text fields:
customerTextField
manufacturerTextField
modelTextField
When selecting manufacturerTextField I need the UIPicker associated with https://www.example.com/example/Manufacturer.php
to appear.
This UIPicker by design has two columns that are populated using JSON data. When making the selection the UIPicker populates both manufacturerTextField
and modelTextField
When the user selects customerTextField I would like the UIPickerView to show the data from https://www.example.com/example/customer.php
This should only be a single column selection.
UPDATED ISSUE:
The following is what I currently have, for some reason when selecting customerTextField the UIPicker with two columns comes up with manufacturerTextField data.
import UIKit
class CreateRMA_ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate, UITextFieldDelegate {
@IBOutlet weak var customerTextField: UITextField!
@IBOutlet weak var manufacturerTextField: UITextField!
@IBOutlet weak var modelTextField: UITextField!
var selectedTextField = UITextField()
struct Category {
var name: String
var items: [String]
}
var allCategories = [Category]()
var selectedCategory:Category?
var selectedItem: String?
var pickerView: UIPickerView!
var values: [AnyObject] = []
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
selectedTextField = textField
pickerView.isHidden = false
return true
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
if selectedTextField == customerTextField {
return 1
} else if selectedTextField == manufacturerTextField {
return selectedCategory == nil ? 1 : 2
} else {//modelTextField
return 2
}
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if selectedTextField == customerTextField {
return values.count
} else if selectedTextField == manufacturerTextField {
return component == 0 ? allCategories.count : selectedCategory?.items.count ?? 0
} else {//modelTextField
return selectedCategory?.items.count ?? 0
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if selectedTextField == customerTextField {
return values[row] as? String
} else if selectedTextField == manufacturerTextField {
if component == 0 {
return allCategories[row].name
} else {
return selectedCategory?.items[row]
}
} else {//modelTextField
return selectedCategory?.items[row]
}
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if component == 0 {
selectedCategory = allCategories[row]
manufacturerTextField.text = allCategories[row].name
pickerView.reloadAllComponents()
} else {
selectedItem = selectedCategory?.items[row]
modelTextField.text = selectedCategory?.items[row]
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func viewDidLoad() {
super.viewDidLoad()
pickerView = UIPickerView()
pickerView.dataSource = self
pickerView.delegate = self
manufacturerTextField.inputView = pickerView
//get the values from sql/Json
let url = NSURL(string: "https://www.example.com/test/service.php")
let data = NSData(contentsOf: url! as URL)
var tmpValues = try! JSONSerialization.jsonObject(with: data! as Data, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSArray
tmpValues = tmpValues.reversed() as NSArray
reloadInputViews()
for candidate in tmpValues {
if let cdict = candidate as? NSDictionary {
//fullName is the column name in sql/json
let names = cdict["customer"]
self.values.append(names! as AnyObject)
}
}
if let url = URL(string: "https://www.example.com/test/Make_Model.php"),
let data = try? Data(contentsOf: url),
let tmpValues = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [[String:String]] {
let tempCategories = tmpValues?.reduce(into: [String:[String]](), { (dict, value) in
if let manufacturer = value["manufacturer"], let model = value["model"] {
dict[manufacturer, default:[]].append(model)
}
})
for category in (tempCategories ?? [:]) {
allCategories.append(Category(name: category.key, items: category.value))
}
pickerView.reloadAllComponents()
}
}
}
回答1:
When you have multiple text fields having the same picker view as input view you need to keep a reference to the currently selected text field
@IBOutlet weak var customerTextField: UITextField!
@IBOutlet weak var manufacturerTextField: UITextField!
@IBOutlet weak var modelTextField: UITextField!
var selectedTextField = UITextField()
Assign selected textfield to this temp textfield in textFieldShouldBeginEditing
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
selectedTextField = textField
pickerView.reloadAllComponents()
pickerView.isHidden = false
return true
}
And check which textfield is selected in picker view datasource and delegate methods and use appropriate data source.
func numberOfComponents(in pickerView: UIPickerView) -> Int {
if selectedTextField == customerTextField {
return 1
} else if selectedTextField == manufacturerTextField {
return selectedCategory == nil ? 1 : 2
} else {//modelTextField
return 2
}
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if selectedTextField == customerTextField {
return values.count
} else if selectedTextField == manufacturerTextField {
return component == 0 ? allCategories.count : selectedCategory?.items.count ?? 0
} else {//modelTextField
return selectedCategory?.items.count ?? 0
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if selectedTextField == customerTextField {
return values[row] as? String
} else if selectedTextField == manufacturerTextField {
if component == 0 {
return allCategories[row].name
} else {
return selectedCategory?.items[row]
}
} else {//modelTextField
return selectedCategory?.items[row]
}
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if selectedTextField == customerTextField {
customerTextField.text = values[row] as? String
} else if selectedTextField == manufacturerTextField {
if component == 0 {
selectedCategory = allCategories[row]
manufacturerTextField.text = allCategories[row].name
pickerView.reloadAllComponents()
} else {
selectedItem = selectedCategory?.items[row]
modelTextField.text = selectedCategory?.items[row]
}
} else {//modelTextField
modelTextField.text = selectedCategory?.items[row]
}
}
来源:https://stackoverflow.com/questions/55860092/unable-to-use-two-uipickerviews-on-one-viewcontroller