How do I use multiple picker views with different data sources in the same view?

Viewed 3591

I have a view with three picker views in it. Two of the picker views have the same data, an array with the numbers 1 to 100. The third picker view has an array with a list of model railroad track manufacturers in it. I have tagged the picker views using a method I found on this site, but when I run the app, all three picker views have 1 to 100 as their data. I also control-dragged from all picker views to the yellow circle at the top of the view and clicked dataSource and delegate. How do I use multiple picker views with different data sources in one view? Also, in order to make the code run, I had to delete weak from all @IBOutlet statements relating to the picker views. Is this a bad thing to do? I am relatively new to code. Thanks.

Picker View Scene Screen Shot

import UIKit

class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
    //MARK: Properties

    @IBOutlet var layoutLengthPickerView: UIPickerView!
    @IBOutlet var layoutWidthPickerView: UIPickerView!
    @IBOutlet var trackPickerView: UIPickerView!

    override func viewDidLoad() {
        super.viewDidLoad()

        layoutLengthPickerView = UIPickerView()
        layoutWidthPickerView = UIPickerView()
        trackPickerView = UIPickerView()

        layoutLengthPickerView.tag = 0
        layoutWidthPickerView.tag = 1
        trackPickerView.tag = 2
    }

    let numbers = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "100"]

    let manufacturers = ["Atlas True Track", "Atlas Code 100", "Atlas Code 83", "Bachmann Nickel Silver", "Bachmann Steel Alloy", "Kato", "Life-Like Trains Code 100", "LIfe-Like Trains Power-Loc", "Peco Code 100", "Peco Code 83", "Peco Code 75", "Shinohara Code 100", "Shinohara Code 70", "Walthers"]

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

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        if pickerView.tag == 0 {
            return numbers[row]
        } else if pickerView.tag == 1 {
            return numbers[row]
        } else if pickerView.tag == 2 {
            return manufacturers[row]
        }

        return ""
    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        if pickerView.tag == 0 {
            return numbers.count
        } else if pickerView.tag == 1 {
            return numbers.count
        } else if pickerView.tag == 2 {
            return manufacturers.count
        }
        return 1
    }
}
3 Answers

As an alternate way of doing that you can use only one picker view and to do the same thing.

@IBOutlet weak var inputBank: UITextField!    
@IBOutlet weak var inputBranch: UITextField! // Those 2 are the fields I need to set the picker view


@IBOutlet weak var inputAccountNumber: UITextField! // this is an extra textField

private var availableBankDetails: AvailableBankDetails?
private var pickerBanks: [String]?
private var pickerBranches: [String]?
private var pickerView: UIPickerView

private var profileDomain: ProfileDomain

required init?(coder aDecoder: NSCoder) {
    self.profileDomain = ProfileDomain()
    self.pickerView = UIPickerView()
    super.init(coder: aDecoder)
}

override func viewDidLoad() {
    super.viewDidLoad()
    self.pickerView.delegate = self
    createBankPickerView()
    createBranchPickerView()
}

private func loadAvailableBankDetails(completion: @escaping (Bool) -> ()) {
    profileDomain.getAvailableBanks { (boolResponse, jsonResponseBody) in
        if boolResponse {
            self.availableBankDetails = AvailableBankDetails(availableBankDetails: jsonResponseBody)
            self.pickerBanks = self.availableBankDetails!.getAvailableBankDetails()
            completion(true)
        } else {
            self.view.makeToast(jsonResponseBody["message"].stringValue, duration: 3, position: .bottom, title: "Error")
            completion(false)
        }

    }
}

private func loadAvailableBranchDetails(bankName: String) -> [String] {
    pickerBranches = availableBankDetails?.getAvailableBranches(bank: bankName)
    return (availableBankDetails?.getAvailableBranches(bank: bankName))!
}

private func createBankPickerView() {
    loadAvailableBankDetails { (boolResponse) in
        if boolResponse {
            self.pickerView.selectRow(1, inComponent: 0, animated: true)
            self.inputBank.inputView = self.pickerView
            self.pickerView.backgroundColor = UIColor.lightGray
            self.createToolbar(inputBankOrBranch: self.inputBank)
        } else {
            print("error")
        }
    }

}

private func createBranchPickerView() {
    self.pickerView.selectRow(1, inComponent: 0, animated: true)
    self.inputBranch.inputView = self.pickerView
    self.pickerView.backgroundColor = UIColor.lightGray
    self.createToolbar(inputBankOrBranch: self.inputBranch)
}

func createToolbar(inputBankOrBranch: UITextField) {
  let toolbar = UIToolbar()
  toolbar.sizeToFit()
  toolbar.tintColor = UIColor.darkGray
  toolbar.backgroundColor = UIColor.blue
  let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(self.closePickerView))
  toolbar.setItems([doneButton], animated: false)
  toolbar.isUserInteractionEnabled = true
  inputBankOrBranch.inputAccessoryView = toolbar
}

@objc func closePickerView() {
    view.endEditing(true)
}

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

func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    if (inputBank.isFirstResponder) {
        return pickerBanks!.count
    } else{
        if pickerBranches == nil {
            return 0
        }
        return pickerBranches!.count
    }
}

func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
    if (inputBank.isFirstResponder){
        return pickerBanks![row]
    } else {
        return pickerBranches![row]
    }
}

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    if inputBank.isFirstResponder {
        inputBank.text =  pickerBanks![row]
        inputBranch.text = ""
        self.pickerBranches = loadAvailableBranchDetails(bankName: inputBank.text!)
    } else {
        if pickerBranches == nil {
            inputBranch.text = ""
        } else {
            inputBranch.text = pickerBranches![row]
        }
    }        
}

func pickerView(_ pickerView: UIPickerView, widthForComponent component: Int) -> CGFloat {
    return 100.0
}

func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
    return 60.0
}

func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {


    var label:UILabel

    if let v = view as? UILabel{
        label = v
    }
    else{
        label = UILabel()
    }

    label.textColor = UIColor.black
    label.textAlignment = .left
    label.font = UIFont(name: "Helvetica", size: 16)



    if inputBank.isFirstResponder {
        label.text = pickerBanks![row]
    } else {
        label.text = pickerBranches![row]
    }

    return label
}
Related