Search code examples
iosswiftuipickerviewuialertview

Problem populating textfield from UIPickerView in an AlertController


Noob with a problem. I'm trying to use an alert controller that will take two inputs: one from a textfield, which will be manually entered text, the other is a selection from a UIPicker. The text portion works fine; the problem I'm having is with the Picker.

The PickerView displays as I want; the problem I am having is registering the selection. As a noob, I full anticipate that is something idiotically stupid that I'm doing (which is why you see all the print statements); however, after many attempts and searches, I can't figure out what that stupid mistake is that I'm missing. I've tried borrowing from other solutions, which is why the code is getting a bit messy, and why I'm now turning here for help.

Thanks for any assistance you can provide

import UIKit
import PMAlertController

class TableViewController: UITableViewController {
    
    var dummyArray = ["A", "B", "C", "D", "E"]
    var dummyStores = ["1", "2", "3", "4"]
    var inputString: String = ""
    var pickerView = UIPickerView()
    var selectedStore: String?
    var storeTextField: String?
    var textLabel = UITextField()
        
    override func viewDidLoad() {
        super.viewDidLoad()
        
    }
    
    // MARK: - Table view data source
    
    override func numberOfSections(in tableView: UITableView) -> Int {

        return 1
    }
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return dummyArray.count
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "itemCell", for: indexPath)
        cell.textLabel?.text = dummyArray[indexPath.row]
        cell.textLabel?.textAlignment = .center
        return cell
    }
    
    
    @IBAction func addButtonPressed(_ sender: UIBarButtonItem) {
        print ("Add Button Pressed")
        var itemTextField = UITextField()
        var storeTextField = UITextField()

        let screenSize = UIScreen.main.bounds
        
        let alertVC = PMAlertController(title: "A Title", description: "My Description", image: UIImage(named: "img.png"), style: .alert)

        let pickerFrame = UIPickerView(frame: CGRect(x:5, y: 20, width: screenSize.width - 20, height: 140))
        pickerFrame.tag = 555
        pickerFrame.delegate = self
        pickerView.delegate = self
        pickerView.dataSource = self

        alertVC.addTextField { (textField2) in
            textField2?.placeholder = "enter item name here"
            itemTextField = textField2!
        }
        
        
        alertVC.addTextField { (textField) in
            textField?.placeholder = "select store here"
            textField?.inputView = pickerView
            
            pickerView.delegate = self
            pickerView.dataSource = self
            
            let toolbar = UIToolbar()
            toolbar.barStyle = UIBarStyle.default
            toolbar.isTranslucent = true
            
            textField?.inputAccessoryView = toolbar
            textField?.inputView = pickerView
            
            storeTextField = textField!
        }
        
        alertVC.addAction(PMAlertAction(title: "Cancel", style: .cancel, action: { () -> Void in
            print("Capture action Cancel")
        }))
        
        alertVC.addAction(PMAlertAction(title: "OK", style: .default, action: { () in
            print("Capture action OK")
            print(itemTextField.text)
            print(storeTextField.text)
            
            self.dummyArray.append(itemTextField.text!)
            self.tableView.reloadData()
            
        }))
        self.present(alertVC, animated: true, completion: nil)
        
    }

}


extension TableViewController: UIPickerViewDataSource {
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }
    
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return dummyStores.count
    }
    
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return dummyStores[row]
    }
    
}

extension TableViewController: UIPickerViewDelegate {
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        selectedStore = dummyStores[row]
        textLabel.text = selectedStore
    }
}

Solution

  • Seems you created a text field textLabel (confusing name by the way, because of UILabel) which you use in the picker view delegate selection method, but when you created the text field that triggers the picker view, you aren't connecting the text field to the class' corresponding property. Instead you have created a local variable storeTextField and set that to the text field.

    This won't do anything because you lose the reference to that text field as soon as the context clears. Essentially you could replace:

    storeTextField = textField!
    

    with:

    self.textLabel = textField!
    

    And you should presumably see what you are aiming to accomplish.

    You also have a property called storeTextField but that's a String? for some reason.

    Just a tip: you (and others on SO) will find it much easier to debug your code if you use meaningful variable names that are consistent with the types they represent. You also have a lot of redundant / unnecessary code in your code sample, such as when you create a UIPickerView instance called pickerFrame that you never use, when you initialize storeTextField and itemTextField but then immediately replace those variables with new values, or when you set the pickerView dataSource and delegate or set the inputView multiple times.