简体   繁体   中英

Passing data from a UIPickerView to a UIViewController in Swift 5

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM