Reputation: 6522
I am creating UIPickerView
programatically and then adding it to UIAlertController
. I've also created a class called StringPickerDelegate
, which implements the picker's delegate and data source protocols.
Here's my code when creating the UIPickerView
let pickerView = UIPickerView(frame: CGRect(x: 5, y: 20, width: 250, height: 140))
alertController.view.addSubview(pickerView)
let delegate = StringPickerDelegate(items: items) { index, item in
onItemSelected?(item)
}
pickerView.dataSource = delegate
pickerView.delegate = delegate
And here's the StringPickerDelegate
class
class StringPickerDelegate: NSObject, UIPickerViewDelegate, UIPickerViewDataSource {
private let items: [String]
private let didSelectItem: ((Int, String) -> Void)
init(items: [String], didSelectItem: @escaping ((Int, String) -> Void)) {
self.items = items
self.didSelectItem = didSelectItem
}
// MARK: UIPickerViewDataSource
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return items.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return items[row]
}
// MARK: UIPickerViewDelegate
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
didSelectItem(row, items[row])
}
}
I really can't comprehend why the methods are not getting called. The class properly implements both delegates and I'm also making sure that UIPickerView
is getting allocated and added as a subview before settings the delegate and data source.
Edit: I've also tried settings delegates AFTER the UIAlertController
is presented to make sure all of the views are fully instantiated, but the result is the same.
Upvotes: 0
Views: 99
Reputation: 271390
UIPickerView.delegate
is declared as weak
(as is most other delegates):
weak var delegate: UIPickerViewDelegate? { get set }
This means that the picker only holds a weak reference it. After your code executes, nothing else would hold a strong reference to the StringPickerDelegate
, so it will be deinitialised!
You need to store an instance of StringPickerDelegate
in your VC:
// outside of any method
var pickerDelegate: StringPickerDelegate?
// ...
pickerDelegate = StringPickerDelegate(items: items) { index, item in
onItemSelected?(item)
}
pickerView.dataSource = pickerDelegate!
pickerView.delegate = pickerDelegate!
Upvotes: 2