Manage a UIPickerView from an External Class - Using Swift
Subclass Pickerview
class MyPickerView: UIPickerView, UIPickerViewDataSource, UIPickerViewDelegate {
var oficinas = ["oficina 1", "Oficinas 2", "Oficina 3"]
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return oficinas.count
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return oficinas[row]
}
}
Main View Controller with Outlet for the PickerView
class MainViewController: UIViewController {
@IBOutlet weak var myPickerView: UIPickerView!
var pickerOficinas: MyPickerView!
override func viewDidLoad() {
//how do I hookup my picker view class
pickerOficinas = MyPickerView()
myPickerView.delegate = pickerOficinas
myPickerView.dataSource = pickerOficinas
}
}
UIPickerView with external DataSource and Delegate in Swift
Both delegate
and datasource
are unowned references. This means that c1
and c2
will get released as soon as you go out of scope. Try declaring c1
and c2
as properties of the class.
Unowned references do not create a strong hold on the referred object (a.k.a. they don't increase the retain count in order to prevent ARC from deallocating the referred object).
Also make sure you remove the delegate and datasource properties of the pickerviews from the interface builder.
class WeightWheelInputViewController: UIViewController {
@IBOutlet weak var picker1: UIPickerView!
@IBOutlet weak var picker2: UIPickerView!
var c1 : WeightWheelController!
var c2 : WeightWheelController!
override func viewDidLoad() {
super.viewDidLoad()
c1 = WeightWheelController(pickerInterval: 150)
c2 = WeightWheelController(pickerInterval: 10)
picker1.dataSource = c1
picker1.delegate = c1
picker2.dataSource = c2
picker2.delegate = c2
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
How conform to UIPickerViewDelegate and UIPickerViewDataSource outside of a ViewController?
When I attempt to define a separate class called 'PickerDelegate' that conforms to UIPickerViewDelegate & UIPickerViewDataSource, I get this error in Xcode:
Simply make your PickerDelegate a subclass of NSObject.
class PickerDelegate : NSObject, UIPickerViewDelegate, UIPickerViewDataSource {
This is no imposition, and is necessary, because Cocoa is Objective-C and won't even be able to see your delegate and data source methods otherwise.
Changing data of UIPickerView Swift
You need to reload the 2nd picker when the value in the 1st picker changes.
func pickerView(_ picker: UIPickerView, didSelectRow row: Int, inComponent component: Int)
{
if (picker == leaguePicker) {
x = row
clubPicker.reloadAllComponents()
}
}
You also need to fix the numberOfRowsInComponent
:
func pickerView(_ picker: UIPickerView, numberOfRowsInComponent component: Int) -> Int
{
switch (picker){
case leaguePicker:
return league.count
case clubPicker:
return club[x].count
default:
return 1
}
}
And your titleForRow
can be simplified:
func pickerView(_ picker: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
switch (picker){
case leaguePicker:
return league[row]
case clubPicker:
return club[x][row]
default: return "an error occurred"
}
}
I also suggest you renamed your x
variable to something more useful such as selectedLeague
.
How to use other class() delegates and datasource func in swift?
You can do it using create Base class and extends in ChildClass or whenever you want to use
example:
SuperBaseViewController Class
class SuperBaseViewController: UIPickerViewDataSource, UIPickerViewDelegate{
//Add PickerView's Data Source and Data Delegate Methods Here
}
SubViewController Class
class SubViewController: SuperBaseViewController{
//Whenever you click on PickerView's row than it's delegate method in SuperBaseViewController if you add didSelect method
}
UIPickerView on Swift 3
Use this method, see the use of _
before pickerview. That is the only problem
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
}
UIPickerView best practice?
It depends on controller appearance. If there only one choose action per screen it will be better to put Table View
on it and selected row will be current selection.
If screen has multiply fields, that user should act with, then, in my opinion, it's better to put label
+ button
above it and when user press this button
you just shows Picker View
from screen bottom. When user select any row in Picker View
you change label text, but don't hide picker itself, it should be done by pressing "Done" button
you place above.
Hope this helps.
Update:
Your problem because you just forget to set dataSource
property of UIPickerView
Just do: gradePicker.dataSource = self
in viewDidLoad()
And don't forget to implements protocol here: class RegisterViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource
Update 2:
Finally made it. If you add UIPickerView
in inputView of your textFiled, then It should NOT be in IB. So you could remove it from storyboard (or .xib, if you use it).
Then change code to be something like this:
class RegisterViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
@IBOutlet weak var gradeTextField: UITextField!
var gradePicker: UIPickerView!
let gradePickerValues = ["5. Klasse", "6. Klasse", "7. Klasse"]
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int{
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
return gradePickerValues.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return gradePickerValues[row]
}
func pickerView(pickerView: UIPickerView!, didSelectRow row: Int, inComponent component: Int){
gradeTextField.text = gradePickerValues[row]
self.view.endEditing(true)
}
override func viewDidLoad() {
super.viewDidLoad()
gradePicker = UIPickerView()
gradePicker.dataSource = self
gradePicker.delegate = self
gradeTextField.inputView = gradePicker
gradeTextField.text = gradePickerValues[0]
}
}
Related Topics
Make a Uiwebview as Height as Its Content with Auto Layout
Pausing Spritekit Game Using Appdelegate in iOS8
iOS - Send Image to Instagram - Documentinteraction
iOS Swift Detecting Image Rotation
Swiftui Multiple Navigationlinks in Form/Sheet - Entry Stays Highlighted
Error When Decoding Certain Base64 Strings, But Not Others
Get Latitude and Longitude Center of Google Map
Could Not Build Module 'Nanopb' Error in Xcode 12.0.1
How to Create a CSV File from Core Data (Swift)
Libmobilegestalt Mobilegestalt.C:890: Mgisdeviceoneoftype Is Not Supported on This Platform
Swipe to Delete on a Tableview That Is Inside a Pageviewcontroller
Locationmanager Didupdatelocations Fires Twice on Device, Only Once on Simulator
Read Uiapplicationlaunchoptionsurlkey in Swift
Swiftui - Navigationview Title and Back Button Clipped Under Status Bar After Orientation Change
Setting Uiimageview Image Affects Layout Constraints
Get the Value of Variable Out of Closure Swift
How to Get All Keys and Values into Separate String Arrays from Nsdictionary in Swift