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