How to use two UIPickerViews in one view controller?

别说谁变了你拦得住时间么 提交于 2019-11-27 12:43:16
andrewcbancroft

Based on the information I have in the question, I'd say that you need to set up the data source & delegate methods to handle the ability to distinguish between which picker instance is calling them.

Using the tag property on the picker view is one strategy.

There should be some if/else or switch statements in the methods that have varying logic depending on whether it's the location or the position picker that's being referenced.

LAOMUSIC ARTS

Here is my solution:

  • in the storyboard, add two UIPickerView instances to your view
  • set the first picker's tag as 1 and set 2 for the second picker under the "Attributes Inspector"
  • control + drag from each picker to the top yellow view controller icon and choose dataSource. Repeat the same choosing delegate
  • add UIPickerViewDataSource and UIPickerViewDelegate to your view controller:

    class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
    
  • in your view controller class, create empty arrays for the pickers:

    var picker1Options = []
    var picker2Options = []
    
  • In viewDidLoad(), populate the arrays with your content:

    picker1Options = ["Option 1","Option 2","Option 3","Option 4","Option 5"]
    picker2Options = ["Item 1","Item 2","Item 3","Item 4","Item 5"]
    
  • implement the delegate and data source methods:

    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
        return 1
    }
    
    func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        if pickerView.tag == 1 {
            return picker1Options.count
        } else {
            return picker2Options.count
        }
    }
    
    func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
        if pickerView.tag == 1 {
            return "\(picker1Options[row])"
        } else {
            return "\(picker2Options[row])"
        }
    }
    
Diavel Rider

I found this to work.

class SecondViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {

    @IBOutlet weak var textbox1: UILabel!
    @IBOutlet weak var textbox2: UILabel!

    @IBOutlet weak var dropdown1: UIPickerView!
    @IBOutlet weak var dropdown2: UIPickerView!

    var age = ["10-20", "20-30", "30-40"]
    var Gender = ["Male", "Female"]

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

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        var countrows : Int = age.count
        if pickerView == dropdown2 {
            countrows = self.Gender.count
        }

        return countrows
    }

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        if pickerView == dropdown1 {
            let titleRow = age[row]
             return titleRow
        } else if pickerView == dropdown2 {
            let titleRow = Gender[row]
            return titleRow
        }

        return ""
    }

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        if pickerView == dropdown1 {
            self.textbox1.text = self.age[row]
        } else if pickerView == dropdown2 {            
            self.textbox2.text = self.Gender[row]
        }
    }
}

My background is in Android but my answer is very OOP. I would suggest creating different classes to implement the DataSource and Delegate like this:

class PositionDataSourceDelegate : NSObject, UIPickerViewDelegate, UIPickerViewDataSource {
   var position = ["Lifeguard", "Instructor", "Supervisor"]
   var selectedPosition : String?

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

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

    func pickerView(pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? {
       return position[row]
    }

    func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
       selectedPosition = position[row]
    }
}

and then another one for the Location:

class LocationDataSourceDelegate : NSObject, UIPickerViewDelegate, UIPickerViewDataSource {
   var location = ["Up", "Down", "Everywhere"]
   var selectedLocation : String?

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

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

    func pickerView(pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? {
         return location[row]
    }

    func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        selectedLocation = location[row]
   }
}

then in your RegisterJobPosition you need to create an instance of each:

let positionDSD = PositionDataSourceDelegate()
let locationDSD = LocationDataSourceDelegate()

and assign them to the pickers like this:

positionPicker.dataSource = positionDSD
positionPicker.delegate = positionDSD
locationPicker.dataSource = locationDSD
locationPicker.delegate = locationDSD

and you can access the selected position and location using:

positionDSD.selectedPosition 
locationDSD.selectedLocation

Hope this helps you and others and I'm also hoping for some constructive comments of why this is not "swifty"

I think the biggest issue and different to Java is that Java easily allow for attributes to be passed through the constructor. e.g. you could declare class LocationDataSourceDelegate as generic and call it genericDataSourceDelegate and make the constructor accept and Array public genericDataSourceDelegate (String data[]) and be able to make one class where could just simply create objects of. You just instantiate it and pass location the constructor like genericDataSourceDelegate (location)

The problem with your model you will have to create as many delegate classes in one program which is a strain to your compiler.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!