Home > Net >  Issues passing data from uipickerview to uilabel
Issues passing data from uipickerview to uilabel

Time:11-06

I'm having issues getting the selected result from the picker to show in my description when pressing Done. When running the app the description will print ["Male", "Female"]. The end result should have the selected option only inserted into the description.

I'm new to swift and am not sure what I have done wrong to get this outcome. Any help with this would be appreciated. The code is below:

class OnboardingViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {

@IBOutlet weak var collectionView: UICollectionView!
@IBOutlet weak var pageControl: UIPageControl!
@IBOutlet weak var NextButton: UIButton!
@IBOutlet weak var Description: UILabel!

let gender = ["Male", "Female"]

var genderPicker = UIPickerView()
var toolBar = UIToolbar()

var slides: [OnboardingSlide] = []

override func viewDidLoad() {
    super.viewDidLoad()

    NextButton.layer.cornerRadius = NextButton.frame.width / 2
    NextButton.layer.masksToBounds = true
    NextButton.alpha = 0
    
    Description.text = "An ideal daily intake of calories varies depending on age, metabolism and levels of physical activity, among other things. Generally, the recommended daily calorie intake is 2,000 calories a day for women and 2,500 for men."

    Description.numberOfLines = 0
    Description.lineBreakMode = .byTruncatingTail
    view.addSubview(Description)
    
}

@IBAction func genderSelectButton(_ sender: UIButton) {

        genderPicker = UIPickerView.init()
        genderPicker.delegate = self
        genderPicker.dataSource = self
        genderPicker.backgroundColor = UIColor.white
        genderPicker.setValue(UIColor.black, forKey: "textColor")
        genderPicker.autoresizingMask = .flexibleWidth
        genderPicker.contentMode = .center
        genderPicker.frame = CGRect.init(x: 0.0, y: UIScreen.main.bounds.size.height - 300, width: UIScreen.main.bounds.size.width, height: 300)
        self.view.addSubview(genderPicker)
                
        toolBar = UIToolbar.init(frame: CGRect.init(x: 0.0, y: UIScreen.main.bounds.size.height - 300, width: UIScreen.main.bounds.size.width, height: 50))
        toolBar.items = [UIBarButtonItem.init(title: "Done", style: .done, target: self, action: #selector(onDoneButtonTapped))]
        self.view.addSubview(toolBar)
    
    Description.alpha = 0
    
}

@objc func onDoneButtonTapped() {
    toolBar.removeFromSuperview()
    genderPicker.removeFromSuperview()
    Description.text = "You are \(gender)."
    Description.alpha = 100
    NextButton.alpha = 100
    
}

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

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

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

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    Description.text = gender[row]
    print(gender[row])
}

@IBAction func nextButtonClicked(_ sender: Any) {
}

CodePudding user response:

You can either listen to the pickerView(_:didSelectRow:inComponent) and record the row value as the user changes the selection, or ask the picker for its selected row (using the selectedRow(inComponent:) method) when the user taps your done button.

Your Description.text = "You are \(gender)." code doesn't make sense, since gender appears to be an array of gender values. I would expect that to to read Description.text = "You are \(gender[selectedRow])." (assuming you save the selected row to an instance var selectedRow.)

Note that instance variables should begin with lower-case letters, and types should start with upper-case letters. Thus Description should be description.

There is a strong convention in Swift to use case consistently (Class and type names should be upper "camel case" and variables and values should be named with lower camel case.

Another thought:

I would suggest making Gender an enum:

enum Gender: String, CaseIterable {
   case male
   case female
}

Then you can fetch a gender using a 0-based index using Gender.allCases[index] and fetch the string value of a gender using

let aGender: Gender = .male
let genderName: String = aGender.rawValue

You can also create a Gender from a string using Gender(rawValue:). Consider this code:

func genderFromString(_ aString: String) {
    if let genderFromString = Gender(rawValue: aString) {
        print("genderFromString for '\(aString)' = \(genderFromString)")
    } else {
        print("Can't convert '\(aString)' to a Gender")
    }
}

genderFromString("male")

genderFromString("Wombat")

That outputs:

genderFromString for 'male' = male
Can't convert 'Wombat' to a Gender
  • Related