0

I am having trouble populating a UIPickerView with an array of strings with each row being one selection. I am creating a UIPicker outlet in my ViewController class and making changes to my UIPicker as data is generated from the main.async call.

// Creating our UIView Controller WeldFloorController
// WeldFloorController provides functionality to the WeldFloor screen

class WeldFloorController: UIViewController{

    // Defining the regex String to be used
    let regexString = String( """
((?:<div id=\\d{1,3}>)(UID:\\d{1,3})(currentPartNumber:(.{0,20}))(workcenter:(.{0,20}))(cycleTime:(.{0,20}))(curPartCycleTime:(.{0,20}))(partsMade:(.{0,20}))(CycleTimeActual:(.{0,20}))(target:(.{0,20}))(actual:(.{0,20}))(downtime:(.{0,20}))(statusReason:(.{0,30}))(lineStatus:(.{0,50}))(efficiency:(.{0,20}))(plusminus:(.{0,20}))(curProdTime:(.{0,30}))(<\\/div>))
""");

    // Defining Main Thread for Data updates
    let main = DispatchQueue.main;

    // Intializing all usable objects on screen
    @IBOutlet weak var weldFloorProductionPicker: UIPickerView!;
    @IBOutlet weak var weldFloorDataDisplay: UICollectionView!;

    // Configuring objects on screen happens within viewDidLoad()
    // P*S Since the exectution is happening asynchronous so
    // all updates must be made from within WorkcenterStatus.sharedInstance.run { }
    override func viewDidLoad() {

        // INITIAL CONFIGURATION OF OBJECTS (SUCH AS defaultText etc..) DONE HERE


        // END CONFIG

        // Starting WebService
        WorkcenterStatus.sharedInstance.run { result in
            switch result {

            // If Successful then execute main.async
            // In other words execute everything in .success
            // when webService == Successful
            // [execute main.async] { code here }

            case .success(let htmlBody): self.main.async {
                // First operation -- Return all matches into an array of Strings
                let returnHtml = matches(for: self.regexString, in: htmlBody);

                // Second operation -- For each match return an integer
                let dataPoints = returnHtml.count;

                // Third operation -- Populate our UICollections with our data                   
                // Sub Operation #1 -- Creating the dataSource
                // Edit** I kept this here for one thing ^^ DataSources should be called
                // from a seperate class file or library -- Using dataSources built within
                // the viewController are not reusable unless the dataSource is delegated
                // to another ViewController which at the point it would be just better
                // to create another lib file
                // and call that from there

                // Sub Operation #1 Actual -- Setting a dataSource object


                self.weldFloorProductionPicker.dataSource = returnHtml[];

                };

            // If failed then print error
            case .failure(let error): print(error)
            };
        };
        // Additional Setup
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    };
};

self.weldFloorProductionPicker.dataSource = returnHtml[]; Is this not a valid way to identify that I want to set the dataSource as the array and all its values? The Array is 1 dimensional and the error I am getting is Cannot subscript a value of type '[String]' with an index of type '()' Any help would be greatly appreciated

Thanks,

3
  • Just remove the []. And this is Swift: No trailing semicolons! Commented Jul 18, 2019 at 15:16
  • Hey @vadian thanks for the reply! I know I have seen you on another question of mine - habits die hard what I can say! Anyhow I did as you advised and I am now returning a Cannot assign value of type '[String]' to type 'UIPickerViewDataSource?' Any ideas?? Commented Jul 18, 2019 at 16:00
  • Basically your approach is wrong. Follow Sh_Khan's suggestion. Commented Jul 18, 2019 at 16:02

1 Answer 1

1

You can try

class ViewController: UIViewController , UIPickerViewDelegate,UIPickerViewDataSource {

   var arr = [String]()

  override func viewDidLoad() {   
    super.viewDidLoad()

    self.weldFloorProductionPicker.delegate = self
    self.weldFloorProductionPicker.dataSource = self 

    WorkcenterStatus.sharedInstance.run { result in

        switch result { 
          case .success(let htmlBody):  
            let returnHtml = matches(for: self.regexString, in: htmlBody)
               self.arr = returnHtml 
                DispatchQueue.main.async {
                  self.weldFloorProductionPicker.reloadAllComponents()
                }
            }

        // If failed then print error
        case .failure(let error): 
              print(error)
        }
    }
  }

    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return arr.count
    }

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return arr[row]
    }

} 
Sign up to request clarification or add additional context in comments.

1 Comment

Could you explain a bit what you are doing?? You switched the class structure around - are you extending the ViewController Class when you do class ViewController: UIViewController , UIPickerViewDelegate,UIPickerViewDataSource {

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.