When I tap on the textField, the input area appear, but there's only 1 row, with blank content. (I expect 3 rows: a,b and c)
I changed the returned value in numberOfRowsInComponent and titleForRow functions to constants, but get the same result (1 blank row). Maybe, these 2 functions never be called.
Please help me!
//In ViewDidLoad Function (ViewController.swift):
let myPickerView: MyPickerView = MyPickerView(arrData: ["a","b","c"]){ selected in
print(selected)
}
textField.inputView = myPickerView.picker
//In MyPickerView.swift
class MyPickerView: NSObject, UIPickerViewDelegate, UIPickerViewDataSource {
var arrData: Array<String>
var picker: UIPickerView
var action: (_ selected: String) -> Void
public init(
arrData: Array<String>,
action: #escaping (_ selected: String) -> Void
) {
self.arrData = arrData
self.action = action
self.picker = UIPickerView()
super.init()
self.picker.delegate = self
self.picker.dataSource = self
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return self.arrData.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return self.arrData[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
self.action(self.arrData[row])
}
}
I found the problem. When I changed myPickerView to global variable (put outside of ViewDidLoad), everything fined.
var myPickerView: MyPickerView?
//In ViewDidload
myPickerView = MyPickerView(arrData: ["a","b","c"]){ selected in
print(selected)
}
Related
I believe I have followed the steps to implement a UIPickerView to display an array of strings. For some reason, the text from titleForRow is hidden. I seems like the picker view is getting the array count because I have the ability to scroll. I just can't get the list if names. I am using UIStoryboard and all outlets are connected. Any help would be appreciated.
extension SongPlayerViewController: UIPickerViewDataSource, UIPickerViewDelegate {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return hertzArray.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return hertzArray[row]
}
//when user selects row
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
}
}
class SongPlayerViewController: UIViewController {
let hertzArray = ["432Hz", "528Hz", "174Hz", "396Hz", "417Hz", "639Hz", "741Hz", "852Hz"]
#IBOutlet weak var pickerView: UIPickerView!
#IBOutlet weak var toolBar: UIToolbar!
//when view did load
override func viewDidLoad() {
super.viewDidLoad()
pickerView.dataSource = self
pickerView.delegate = self
}
}
I don't think there is a problem with the code you've posted. I put it into a playground with a little bit of setup code and it works. You should check your outlets in the nib file and check at runtime to ensure that the pickerView property is being assigned. As suggested in comments, check the dimensions of the picker using the view debugging tools
(https://developer.apple.com/library/archive/documentation/ToolsLanguages/Conceptual/Xcode_Overview/ExaminingtheViewHierarchy.html)
Here's the Playground I was working with:
import UIKit
import PlaygroundSupport
class SongPlayerViewController: UIViewController {
let hertzArray = ["432Hz", "528Hz", "174Hz", "396Hz", "417Hz", "639Hz", "741Hz", "852Hz"]
#IBOutlet weak var pickerView: UIPickerView!
override func loadView() {
let pickerView = UIPickerView()
self.pickerView = pickerView
view = UIView(frame: CGRect(x: 0, y: 0, width: 320, height: 480))
view.addSubview(pickerView)
pickerView.translatesAutoresizingMaskIntoConstraints = false
}
override func viewDidLoad() {
super.viewDidLoad()
pickerView.dataSource = self
pickerView.delegate = self
}
}
extension SongPlayerViewController: UIPickerViewDataSource, UIPickerViewDelegate {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return hertzArray.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return hertzArray[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
}
}
let songController = SongPlayerViewController()
PlaygroundSupport.PlaygroundPage.current.liveView = songController
var Months = ["A","B","C","D"]
var pickerview = UIPickerView()
#IBOutlet var txt_Month: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
pickerview.isHidden = true
pickerview.dataSource = self
pickerview.delegate = self
txt_Month.inputView = pickerview
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return Months.count
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
{
txt_Month.text = Months[row]
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?
{
return Months[row]
}
maybe it's because pickerview is hidden?
Set the pickerview is unhide.
pickerview.isHidden = false
I try to use this method selectedRow(inComponent: 0), yet it doesn't work for me. Any way out to get the first/default value from picker when it is not active?
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return countries.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return countries[row].name
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
country.text = countries[row].name //`country.text` is just textField
}
}
Not a big deal-
Just define your picker view as global and access the value for objectAtIndex(0)
And write this line of code in viewDidLoad()
Not exact, but something like this-
#IBOutlet var yourPicker: UIPickerView! = UIPickerView()
var yourArray = ["Apple", "Samsung", "Nokia"]
override func viewDidLoad() {
super.viewDidLoad()
yourPicker.text = yourArray[0]
}
I am having at bit og trouble with my PickerView. First my ViewController does not accept UIPickerViewDataSource no matter what I do. Second, the PickerView will only show the first row. I need it to show both rows and display in one TextField called school
What do I do wrong ?????
Can anyone help me before I go crazy
enter code here
private let typeComponent = 0
private let areaComponent = 1
private let typeOption = ["HighSchool of", "College of", "University of"]
private let areaOption = ["Miami", "Los Angeles", "New York"]
// PickerView - School 2 af 5
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 2
}
// PickerView - School 3 af 5
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if component == typeComponent {
return typeOption.count
} else {
return areaOption.count
}
}
// PickerView - School 4 af 5
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if component == typeComponent {
return typeOption[row]
} else {
return areaOption[row]
}
}
// PickerView - School 5 af 5
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
// school.text = pickOption[component][row]
let typeRow = pickerView.selectedRow(inComponent: (0))
let areaRow = pickerView.selectedRow(inComponent: (1))
let type = typeOption[typeRow]
let area = areaOption[areaRow]
school.text = "\(type)\(area)"
}
override func viewDidLoad() {
super.viewDidLoad()
//Placeholder TextView Interest and about 1 ag 3
Interest.delegate = self
Interest.text = "What are your interests..."
Interest.textColor = UIColor.lightGray
about.delegate = self
about.text = "Tell about yourself..."
about.textColor = UIColor.lightGray
//PickerView School 1 af 5
let pickerView = UIPickerView()
pickerView.delegate = self
pickerView.dataSource = self
pickerView.backgroundColor = UIColor.white
school.inputView = pickerView
Implement all the required methods of UIPickerViewDataSource. If you not conform to UIPickerViewDataSource it will give you error.
Methods which is Required to implement in your conforming class
in Swift 2.0
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int
in Swift 3.0
func numberOfComponents(in pickerView: UIPickerView) -> Int
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int
Make sure your class conforms to UIPickerViewDataSource protocol like this:
class YourViewController: UIPickerViewDataSource {
//
}
Updated:
For Swift 3 you have to use this datasource function:
func numberOfComponents(in pickerView: UIPickerView) -> Int{
}
and not the one you used.
When using a dictionary to populate a UIPickerView in Swift, how do I specify that the key is to be used as the title for row, while the value is used to perform calculations, such as to set the value for selectedPower, below?
If I were using an array of floats, I'd set it up as below, but how do I do it with a dictionary?
class DiagnosticORViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
var selectedPower : Float!
let FitAssessment : [String : Float] = ["0.50 flat" : -0.50, "0.25 flat" : -0.25, "aligned" : 0, "0.25 steep" : 0.25, "0.50 steep" : 0.50]
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return FitAssessment.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return "\(FitAssessment[row])"
}
func pickerView(pickerView: UIPickerView!, didSelectRow row: Int, inComponent component: Int) {
selectedPower = FitAssessment[row]
}
Two separate arrays solves the problem.
class DiagnosticORViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
var selectedPower : Float!
let FitDescription : [String] = ["0.50 flat", "0.25 flat", "aligned", "0.25 steep", "0.50 steep"]
let FitValue : [Float] = [ -0.50, -0.25, 0, 0.25, 0.50]
#IBOutlet weak var fitAssessmentPicker: UIPickerView!
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return FitDescription.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return FitDescription[row]
}
func pickerView(pickerView: UIPickerView!, didSelectRow row: Int, inComponent component: Int) {
selectedPower = FitValue[row]
}
This morning I had a similar issue.
Since I am reading data from data-base, and fill the picker, I also need IDs of such data.
I will paste a very basic code on how to realize your question with a stupid example I came with:
P.S. It might be late for you, but might be useful for someone else.
import UIKit
class selectLanguage: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource
{
var pickerData = [String:Int]()
#IBOutlet weak var pickerControl: UIPickerView!
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
pickerData["English"] = 0
pickerData["German"] = 1
pickerData["Serbian"] = 2
pickerData["French"] = 3
pickerData["Italian"] = 4
self.pickerControl.delegate = self
self.pickerControl.dataSource = self
}
// Connect data to picker:
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// The number of columns of data
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
// The number of rows of data
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerData.count
}
// The data to return for the row and component (column) that's being passed in
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
// builtInCommands[pickerData[row]]
return "\(Array(pickerData.keys)[row])"
}
//Results of selection
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
let key = Array(pickerData.keys)[row]
let value = pickerData[key]
print(">>>Selected Language is: \(key), and its id is : \(value!)")
}
}
Dictionaries are unordered, so it is better to use an Array of named tuples
let FitAssessment:[(myKey: String, myValue: Double)] = [("0.50 flat", -0.50), ("0.25 flat", -0.25), (etc....)]
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return FitAssessment.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return FitAssessment[row].myName
}
func pickerView(pickerView: UIPickerView!, didSelectRow row: Int, inComponent component: Int) {
selectedPower = FitAssessment[row].myValue
}