Search code examples
swiftdelegatesiboutletviewdidloadpicker

Xcode Swift 3 Picker: Putting the DataSource in ViewDidLoad


I am trying to set up a picker that would display different results based on certain conditions. The only issue is that I need to put the dataSource (picker data that will display) outside the viewDidLoad. I need the viewDidLoad to load the appropriate data if the condition was met. However, with code dealing with pickers that I've seen, it seems the dataSource array is placed outside the viewDidLoad (I presume so the delegate methods can use that value). I am just wondering if I can place this dataSource into viewDidLoad so that it would recognize it, or if there was a way to run a Switch or If statement outside the viewDidLoad and in the class.

import UIKit
import Parse

class VC: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {

    var pickerData = [String]()

    @IBOutlet weak var namePicker: UIPickerView!

    override func viewDidLoad() {
        super.viewDidLoad()

        namePicker.dataSource = self
        namePicker.delegate = self


        //here I want the picker to show something different depending on the value of nameOfPerson. I changed the order of the array because the picker selects the first name of the array as the default. 
        switch nameOfPerson
        {
        case "Carly": 
            let pickerData = ["Carly","Jeff","Bob","Anita"]
        case "Jeff": 
            let pickerData = ["Jeff","Carly","Bob","Anita"]
        case "Bob": 
            let pickerData = ["Bob","Carly","Jeff","Anita"]
        case "Anita": 
            let pickerData = ["Anita","Carly","Jeff","Bob"]
        }
    }
   func numberOfComponents(in pickerView: UIPickerView) -> Int {
    return 1
    }
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    return pickerData.count
    }
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
    return pickerData[row]
    }
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
    {

    }
}

Solution

  • I am just wondering if I can place this dataSource into viewDidLoad so that it would recognize it, or if there was a way to run a Switch or If statement outside the viewDidLoad and in the class

    No. The data source methods must be methods, i.e. functions at the top level of the class, in order for Objective-C to see them. Therefore the data itself must be visible to the data source methods, and the only coherent way to share data between viewDidLoad and the data source methods is as a property, like your var pickerData.

    What's wrong with your code is the let:

        case "Carly": 
            let pickerData = ["Carly","Jeff","Bob","Anita"]
        case "Jeff": 
            let pickerData = ["Jeff","Carly","Bob","Anita"]
        case "Bob": 
            let pickerData = ["Bob","Carly","Jeff","Anita"]
        case "Anita": 
            let pickerData = ["Anita","Carly","Jeff","Bob"]
        }
    

    Delete the term let from each of those cases! Otherwise you are just setting a temporary local variable pickerData, which is not what you want to do. You want to set the property that you declared like this:

    var pickerData = [String]()
    

    ....and your code is not doing that! What you want is this:

    case "Carly": 
        self.pickerData = ["Carly","Jeff","Bob","Anita"]
    case "Jeff": 
        self.pickerData = ["Jeff","Carly","Bob","Anita"]
    case "Bob": 
        self.pickerData = ["Bob","Carly","Jeff","Anita"]
    case "Anita": 
        self.pickerData = ["Anita","Carly","Jeff","Bob"]
    }
    

    (Plus you need a default case, of course.)

    Then, at the end, just to be on the safe side, reload the data:

    self.namePicker.reloadAllComponents()