[UILabel numberOfComponentsInPickerView:]: unrecognized selector sent to instance ...]
Asked Answered
O

1

1

In my iOS app I have created a table view controller with custom cells where one of them contains a PickerView. Here's the class for that custom cell:

 import Foundation
 import UIKit

class PickerCell: UITableViewCell {
  @IBOutlet weak var label : UILabel!
  @IBOutlet weak var pickerView : UIPickerView!

func configurePickerCell(labelText:String, pickerDelegate:MyPickerViewController, enabled:Bool, defaultValueIndex:Int) {
    self.label.text = labelText

    var labelFrame:CGRect = self.label.frame
    labelFrame.size.height = Settings.labelHeight
    self.label.frame = labelFrame

    self.pickerView.delegate = pickerDelegate
    self.pickerView.dataSource = pickerDelegate

    if (enabled) {
        self.pickerView.userInteractionEnabled = true
    }

    else {
        self.pickerView.userInteractionEnabled = false
        self.pickerView.selectRow(defaultValueIndex, inComponent: 0, animated: true)
    }
}
}

and here is the picker view controller class:

import Foundation
import UIKit
class MyPickerViewController: UIViewController,UIPickerViewDataSource,UIPickerViewDelegate {

var pickerData:[String]!

init(pickerData: [String]){
    super.init(nibName: nil, bundle: nil)
    self.pickerData = pickerData
}

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    fatalError("init(coder:) has not been implemented")
}

func numberOfComponentsInPickerView(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 pickerData[row]
}

func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    println(self.pickerData[row])
}
}

and are a pair of method in my table view controller:

override func viewWillAppear(animated: Bool) {
    self.tabBarController?.navigationItem.leftBarButtonItem = nil
    self.tabBarController?.navigationItem.setHidesBackButton(false, animated: true)

    self.projectService.requestAllProjects {
        (response) in
        self.projects = self.projectService.loadProjects(response) as! [Project]
        //println(self.projects.count)
        dispatch_async(dispatch_get_main_queue()) {
            self.tableView.reloadData()
        }
    }

    self.userService.requestAllUsers {
        (response) in
        self.users = self.userService.loadUsers(response) as! [User]
        //println(self.users.count)
        dispatch_async(dispatch_get_main_queue()) {
            self.tableView.reloadData()
        }
    }

}

while this is called inside

 override func tableView(tableView: UITableView,
    cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

       ...

        self.projectCell = tableView.dequeueReusableCellWithIdentifier("PickerCell", forIndexPath: indexPath) as! PickerCell
        let pickerController = MyPickerViewController(pickerData: self.projectService.getArrayOfNames(self.projects))
        self.projectCell.configurePickerCell("Progetto", pickerDelegate: pickerController, enabled: true, defaultValueIndex: 0)
        return self.projectCell

     ...
}

The problem is that I get the error in title and I don't know what it means. self.projects is an array of Project objects retrieved from a database with

NSURLSession.sharedSession().dataTaskWithURL()

and it is correctly populated so I don't know where I am making the mistake. Can you help please?

UPDATE Many thanks to @NickCatib, here's my working code. NB: there is no need of a further class as Picker view delegate. I have just implemented it just inside the custom cell:

import Foundation
import UIKit

class PickerCell: UITableViewCell, UIPickerViewDataSource,UIPickerViewDelegate {
  @IBOutlet weak var label : UILabel!
  @IBOutlet weak var pickerView : UIPickerView!

  var pickerData:[String]!

  func numberOfComponentsInPickerView(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 pickerData[row]
  }

  func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    println(self.pickerData[row])
  }

  func configurePickerCell(labelText:String, enabled:Bool, defaultValueIndex:Int) {
    self.label.text = labelText

    var labelFrame:CGRect = self.label.frame
    labelFrame.size.height = Settings.labelHeight
    self.label.frame = labelFrame

    self.pickerView.delegate = self
    self.pickerView.dataSource = self

    if (enabled) {
        self.pickerView.userInteractionEnabled = true
    }

    else {
        self.pickerView.userInteractionEnabled = false
        self.pickerView.selectRow(defaultValueIndex, inComponent: 0, animated: true)
    }
  }
}
Opsonin answered 11/9, 2015 at 11:39 Comment(13)
is cellForRowAtIntexPath inside MyPickerViewController?Sundried
No, it is inside the table view controller. Shall put it inside MyPickerView controller? How?Opsonin
sorry...I'm new to this, overall to picker views :SOpsonin
well I would set delegate for the picker view either in tableview controller or cell itself. basicly I think that best way to deal with these kind of changes of the UIPicker is right away, so try to implement delegate inside the cell or UITableViewController. Since there is a change to have multiple pickers, I would deal with them inside the cell for this particular case.Sundried
well, I think it works. I'll update my question posting my new code. Thank you from heart. Really. Just one thing: the method cellForRowAtIntexPath will always be called AFTER viewWillAppear(), right? Just to be sure that the array are always populated...Opsonin
I will postthis as an answer then. All tableview delegate an datasource methods are called each tine you call reloaddata, so when you get your data relod table and thats it. And yes these methods are called after virw willappearSundried
Posted as an answer :)Sundried
really thank you...you have been a ray of light in this dark day of ios programming!Opsonin
You r welcome, happy coding :)Sundried
Forgive me if I am annoying you again. Some times in this lineOpsonin
self.projectCell.pickerData = self.projectService.getArrayOfNames(self.projects)Opsonin
the app crashes saying: "fatal error: unexpectedly found nil while unwrapping an Optional value". That's why I had asked you if the array are always populated at that point... what could it be?Opsonin
Let us continue this discussion in chat.Sundried
S
1

Well I would set delegate for the picker view either in tableView controller or cell itself. Basically I think that best way to deal with these kind of changes of the UIPicker is right away, so try to implement delegate inside the cell or UITableViewController. Since there is a chance to have multiple pickers, I would deal with them inside the cell for this particular case.

Sundried answered 11/9, 2015 at 12:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.