Manage a Uipickerview from an External Class - Using Swift

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



Leave a reply



Submit