Reputation: 31
I'm currently trying to build a simple app in Swift 5 that has a main UIViewController
:
class TheList: UIViewController{
@IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
(...)
}
The UIViewController
has an Extension that utilises the UITableViewDataSource
and UITableViewDelegate
protocols.
extension TheList: UITableViewDelegate, UITableViewDataSource{
(...)
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch indexPath.row {
case 0:
let cell = tableView.dequeueReusableCell(withIdentifier: "titleViewCell")!
return cell
(...)
}
It populates the table with certain dynamic UITableViewCells
, that are their own, separate classes. Here's an example of one:
class AmtTableViewCell: UITableViewCell{
@IBOutlet var hoursPickerView: UIPickerView!
override func awakeFromNib() {
super.awakeFromNib()
populate()
hoursPickerView.delegate = self
hoursPickerView.dataSource = self
}
(...)
}
extension AmtTableViewCell: UIPickerViewDelegate, UIPickerViewDataSource{
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerData.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return String(pickerData[row])
}
}
As you can see, that UITableViewCell
has an outlet of a UIPickerView
. I would like to somehow pass the data from this class's UIPickerView
to my UIViewController
, so that I can parse it further there. I've tried to create a method to do so and then call it in my View Controller, but from I understood I had to instantiate it first, which kills the point, as I would like to get the value from the instance the user sees on their screen.
I have also tried to create an outlet for the Picker in my View Controller and then set up its Delegate and Data Source as the AmtTableViewCell
class instead of self
but I've learned I can't put that UIPickerView
in my UIViewController
.
Any help is appreciated.
Upvotes: 0
Views: 558
Reputation: 1278
Using closures:
class AmtTableViewCell: UITableViewCell{
@IBOutlet var hoursPickerView: UIPickerView!
var selectedValueInPicker: ((String) -> Void)?
override func awakeFromNib() {
super.awakeFromNib()
populate()
hoursPickerView.delegate = self
hoursPickerView.dataSource = self
}
(...)
}
extension AmtTableViewCell: UIPickerViewDelegate, UIPickerViewDataSource{
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerData.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return String(pickerData[row])
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int){
selectedValueInPicker?(String(pickerData[row]))
}
}
extension TheList: UITableViewDelegate, UITableViewDataSource{
(...)
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch indexPath.row {
case 0:
let cell = tableView.dequeueReusableCell(withIdentifier: "titleViewCell") as? AmtTableViewCell
cell.selectedValueInPicker = { val in
//Do what is needed with the Stirng val that is comming from the cell passes in closure
}
return cell ?? AmtTableViewCell()
(...)
}
Using Protocol delegate
protocol PickerSelectedValue{
func didSelectValueInPicker(value: String)
}
class AmtTableViewCell: UITableViewCell{
@IBOutlet var hoursPickerView: UIPickerView!
var delegate: PickerSelectedValue?
override func awakeFromNib() {
super.awakeFromNib()
populate()
hoursPickerView.delegate = self
hoursPickerView.dataSource = self
}
(...)
}
extension AmtTableViewCell: UIPickerViewDelegate, UIPickerViewDataSource{
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerData.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return String(pickerData[row])
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int){
delegate?.didSelectValueInPicker(String(pickerData[row]))
}
}
extension TheList: UITableViewDelegate, UITableViewDataSource,pickerSelectedValue{
(...)
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch indexPath.row {
case 0:
let cell = tableView.dequeueReusableCell(withIdentifier: "titleViewCell") as? AmtTableViewCell
cell?.delegate = self
return cell ?? AmtTableViewCell()
(...)
func didSelectValueInPicker(value: String){
print("the selected value in picker was",value)
}
}
the delegate protocol is little big long in code, but maybe easier to understand is not confortable with closures.
Upvotes: 1