Search code examples
iosswiftuitableviewpicker

iOS picker inside of a table cell


Have a fun one here

I've got a UIPickerView inside of a UITableViewCell, theses weren't meant to be used this way were they?

So far the picker slides up on click but there's no data in the picker and the done/cancel buttons are not showing up.

Does anybody know if this is possible or know a better way to do it? Here's the code (just trying to get it to work for now)

import Foundation
import UIKit

class HelloworkJobsEditJobViewController: UIViewController{
    fileprivate var presenter: HelloworkJobsEditJobPresenter?

    @IBOutlet weak var editJobTable: UITableView!
    @IBOutlet weak var blurView: UIView!


    func inject(presenter: HelloworkJobsEditJobPresenter) {
        self.presenter = presenter
    }

    var helloworkJob: HelloworkJob!

    let labelData = ["Title","Company",
                     "Location","Job Type",
                     "Min Salary","Max Salary",
                     "Posted Date"]

    let pickerData = ["Full Time", "Part Time", "Casual",
                      "Fixed term","Shiftworkers",
                      "Daily hire and weekly hire",
                      "Probation","Outworkers"]

    var myPicker: UIPickerView! = UIPickerView()
    var pickerTextField: UITextField?
    var picker: UIPickerView?
    let toolBar = UIToolbar()


    var textFieldData = [String]()

    override func viewDidLoad(){
        super.viewDidLoad()
        helloworkJob = presenter?.getHelloworkJob()
        editJobTable.dataSource = self
        editJobTable.delegate = self
        prepareTextFieldData()
        blurBackgroundButton()
        //setUpPickerView()
    }

    func setUpPickerView(){
        picker = UIPickerView(frame: CGRect(x: 0, y: 200, width: view.frame.width, height:300))
        picker!.backgroundColor = .white

        picker!.showsSelectionIndicator = true
        picker!.delegate = self
        picker!.dataSource = self

        toolBar.barStyle = UIBarStyle.default
        toolBar.isTranslucent = true
        toolBar.tintColor = UIColor(red: 76/255, green: 217/255, blue: 100/255, alpha: 1)
        toolBar.sizeToFit()

        let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.plain, target: self, action: Selector("donePicker"))
        let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
        let cancelButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.plain, target: self, action: Selector("donePicker"))

        toolBar.setItems([cancelButton, spaceButton, doneButton], animated: false)
        toolBar.isUserInteractionEnabled = true
    }
    func setPickerTextField(pickerTextField:UITextField){
        setUpPickerView()
        pickerTextField.inputView = picker
        pickerTextField.inputAccessoryView = toolBar
    }


    func blurBackgroundButton(){
        if !UIAccessibilityIsReduceTransparencyEnabled() {
            blurView.backgroundColor = .clear

            let blurEffect = UIBlurEffect(style: .extraLight)
            let blurEffectView = UIVisualEffectView(effect: blurEffect)
            //always fill the view
            blurEffectView.frame = self.view.bounds
            blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

            blurView.addSubview(blurEffectView) //if you have more UIViews, use an insertSubview API to place it where needed
        }
    }

    func prepareTextFieldData(){
        textFieldData.append(helloworkJob.jobTitle)
        textFieldData.append(helloworkJob.companyName)
        textFieldData.append(helloworkJob.jobLocation)
        textFieldData.append(helloworkJob.jobType)
        textFieldData.append(helloworkJob.minSalary)
        textFieldData.append(helloworkJob.maxSalary)
        textFieldData.append(helloworkJob.jobDatePosted)
    }

    @IBAction func tapCloseButton(_ sender: Any) {
        self.dismiss(animated: true, completion: nil)
    }

}

extension HelloworkJobsEditJobViewController: UITableViewDelegate {

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
        return 7
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//        print("click received")
//        if(indexPath.row == 3){
//            print("pass 3")
//            pickerTextField!.resignFirstResponder()
//        }
    }

}

extension HelloworkJobsEditJobViewController: UITableViewDataSource {

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        print("\(#line): \(#function) \(indexPath.row)")


        if(indexPath.row == 3){
            let cellIdentifier = "CommonLabelPickerCell"
            guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? CommonLabelPickerCell else {
                fatalError("The dequeued cell is not an instance of \(cellIdentifier).")
            }

            cell.cellLabel.text = labelData[indexPath.row]
            pickerTextField = cell.pickerTextField
            setPickerTextField(pickerTextField: pickerTextField!)
            return cell
        }else{
            let cellIdentifier = "CommonLabelTextFieldCell"
            guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? CommonLabelTextFieldCell else {
                fatalError("The dequeued cell is not an instance of \(cellIdentifier).")
            }

            cell.cellLabel.text = labelData[indexPath.row]
            cell.cellTextField.text = textFieldData[indexPath.row]
            cell.selectionStyle = .none
            return cell
        }
    }
}

extension HelloworkJobsEditJobViewController: UIPickerViewDelegate{

}
extension HelloworkJobsEditJobViewController: UIPickerViewDataSource{
    // The number of columns of data
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }

    // The number of rows of data
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return pickerData.count
    }

    // The data to return for the row and component (column) that's being passed in
    func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        // not being called
        print(pickerData)
        return pickerData[row]
    }
}

The Table Cell

import Foundation
import UIKit

class CommonLabelPickerCell: UITableViewCell {

    @IBOutlet weak var cellLabel: UILabel!
    @IBOutlet weak var pickerTextField: UITextField!

    //MARK: Properties
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
        // Configure the view for selected state
    }

}

Solution

  • Would suggest using IQDropDownTextField library which supports TextField with DropDown using UIPickerView.

    Follow the below steps to set up and use IQDropDownTextField

    1. Add pod to project Podfile pod 'IQDropDownTextField'
    2. install pod by executing pod install on the terminal
    3. Add the .h file in your bridging header and import to HelloworkJobsEditJobViewController with #import "IQDropDownTextField.h"
    4. set class of text field var pickerTextField: IQDropDownTextField!
    5. In viewDidLoad() setup

      pickerTextField.isOptionalDropDown = false pickerTextField.itemList = pickerData

    Cheers!