I keep getting an "'-[UITableView numberOfComponentsInPickerView:]: unrecognized selector sent to instance" error referencing a method in one of my custom UITableViewCell classes, and I can't seem to figure out why. I've searched through stack overflow but can't find an answer related to my situation. Any ideas? Thanks!
public class PickerTableViewCell:UITableViewCell, UIPickerViewDataSource, UIPickerViewDelegate {
var pickerData:[Array<Int>] = []
#IBOutlet weak var picker: UIPickerView!
public func configure(data:[Array<Int>]) {
pickerData = data
}
// Picker functions
public func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return pickerData.count
}
public func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerData[component].count
}
public func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return String(pickerData[component][row])
}
}
If you look at the error message you see that the method numberOfComponentsInPickerView: was invoked on a UITableView instance.
So you ask the question "why would that method be invoked on a UITableView?"
The method in question is a picker view data source method, so that means that somewhere you assigned a UITableView as a picker view's data source, so that when the picker view was displayed the method call was made against a class (UITableView) that hadn't implemented the delegate method.
In your case it was a simple drag-drop error in Interface Builder.
Related
I'm reading a Swift OOP book and I understand the idea of instance methods having arguments which will be used within the function. What is unclear is while following online tutorials for UIPickerViews and UITableViews, there are methods that have UIPickerView or UITableView objects as parameters but aren't used in the function.
For example:
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
// Return the number of rows of data
return gamesList.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return gamesList[row].name
}
The first parameter pickerView which takes a UIPickerView object isn't used within these functions. I'm wondering why have them as parameters in the method's signature but these objects are rarely used in tutorials? Or am I thinking about this incorrectly?
Thank you in advance for any help to get a better understanding.
The first object from all the Delegate and Datasource methods that you are talking about is not unused object, it will hold the reference of the current UIPickerView, So it will used if you have multiple UIPickerView in the same ViewController. Same thing goes for all the others control like UITableView, UICollectionView etc.
For eg if you have 2 UIPickerView in the same Controller then you can fill the UIPickerView by comparing it in the UIPickerView methods.
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView == firstPickerView {
return gamesList1.count
}
//else return for second pickerView
return gamesList2.count
}
So you need to compare the pickerView reference in all the methods of UIPickerView and fill or access the data according to it.
Let's say I have a stream of dogs private var dogs: Observable<[Dogs]>. Every time a new value is produced my block is called where I create a new dataSource and delegate for my UIPickerView and then within the block I call pickerView.reloadAllComponents() but my view appears with an empty pickerView, even though the dataSource and delegate are queried.
Example code:
self.dataStream
.subscribeNext {
self.dataSource = PickerViewDataSource(data: $0)
self.pickerView.dataSource = self.dataSource
self.delegate = PickerViewDelegate(data: $0, selectedRow: self._selectedRowStream)
self.pickerView.delegate = self.delegate
self.pickerView.reloadAllComponents()
}.addDisposableTo(self.disposeBag)
Debugging the dataSource and delegate I know these are queried and the reason I am keep dataSource and delegate reference in the UIViewController is due to the fact that the UIPickerView holds a weak reference for these.
This one of the last strategies I have tried and still get the same result. Any help would be appreciated. Thanks.
Update:
DogPickerViewDataSource:
class DogPickerViewDataSource: NSObject, UIPickerViewDataSource {
private var dogs: [Dog]
init(
dogs: [Dog]
) {
self.dogs = dogs
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return dogs.count
}
}
DogPickerViewDelegate:
class DogPickerViewDelegate: NSObject, UIPickerViewDelegate {
private var selectedRow: BehaviorSubject<Int>
private var dogs: [Dog]
init(
dogs: [Dog],
selectedRow: BehaviorSubject<Int>
) {
self.dogs = dogs
self.selectedRow = selectedRow
}
func pickerView(pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? {
let dogName = (self.dogs[row].name)!
return NSAttributedString(string: dogName)
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
self.selectedRow.onNext(row)
}
}
If I understand you correctly, on viewDidLoad you're initialising your pickerView with new delegate and data source, calling reloadAllComponents and expecting that everything should be displayed properly. But you're still displaying pickerView from previous view controller. You should try to hide picker view on previous view controller's viewWillDisappear method and display new one in viewDidAppear method of new view controller.
I have problem with a picker view that appears empty when I make it in second view controller.(image1).
When I make it in the first view controller that work fine.
two view controller and pickerview
code:
import UIKit
class ViewController: UIViewController, UIPickerViewDelegate {
var civilite = ["Madame","Monsieur","Mademoiselle"]
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return civilite.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String!{
return civilite[row]
}
}
Xcode 6.4
I found the solution.
I add new file "Cocoa touch class" (Formulaire.swift) I change the custom class of the second view controller to be "Formulaire" [Custom class][1]
[1]: http://i.stack.imgur.com/H4Nip.png
I deplace the code in this file and is work fine.
Thanks
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 5 years ago.
Improve this question
What is the library to make drop down menu in swift? I am new to Xcode and the Swift language, so can anyone please direct me on how to implement the drop down list in swift?
(Swift 3) Add text box and uipickerview to the storyboard then add delegate and data source to uipickerview and add delegate to textbox. Follow video for assistance
https://youtu.be/SfjZwgxlwcc
import UIKit
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, UITextFieldDelegate {
#IBOutlet weak var textBox: UITextField!
#IBOutlet weak var dropDown: UIPickerView!
var list = ["1", "2", "3"]
public func numberOfComponents(in pickerView: UIPickerView) -> Int{
return 1
}
public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
return list.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
self.view.endEditing(true)
return list[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
self.textBox.text = self.list[row]
self.dropDown.isHidden = true
}
func textFieldDidBeginEditing(_ textField: UITextField) {
if textField == self.textBox {
self.dropDown.isHidden = false
//if you don't want the users to se the keyboard type:
textField.endEditing(true)
}
}
}
A 'drop down menu' is a web control / term. In iOS we don't have these. You might be better looking at UIPopoverController. Check out this tutorial for a bit of an insight to PopoverControllers
http://www.raywenderlich.com/29472/ipad-for-iphone-developers-101-in-ios-6-uipopovercontroller-tutorial
Unfortunately if you're looking to apply UIPopoverController in iOS9, you'll get a deprecated class warning. Instead you need to set your desired view's UIModalPresentationPopover property to achieve the same result.
Popover
In a horizontally regular environment, a presentation style
where the content is displayed in a popover view. The background
content is dimmed and taps outside the popover cause the popover to be
dismissed. If you do not want taps to dismiss the popover, you can
assign one or more views to the passthroughViews property of the
associated UIPopoverPresentationController object, which you can get
from the popoverPresentationController property.
In a horizontally compact environment, this option behaves the same as
UIModalPresentationFullScreen.
Available in iOS 8.0 and later.
Reference: https://developer.apple.com/documentation/uikit/uiviewcontroller/1621355-modalpresentationstyle
You have to be sure to use UIPickerViewDataSource and UIPickerViewDelegate protocols or it will throw an AppDelegate error as of swift 3
Also please take note of the change in syntax:
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int
is now:
public func numberOfComponents(in pickerView: UIPickerView) -> Int
The following below worked for me.
import UIkit
class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
#IBOutlet weak var textBox: UITextField!
#IBOutlet weak var dropDown: UIPickerView!
var list = ["1", "2", "3"]
public func numberOfComponents(in pickerView: UIPickerView) -> Int{
return 1
}
public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
return list.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
self.view.endEditing(true)
return list[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
self.textBox.text = self.list[row]
self.dropDown.isHidden = true
}
func textFieldDidBeginEditing(_ textField: UITextField) {
if textField == self.textBox {
self.dropDown.isHidden = false
//if you don't want the users to se the keyboard type:
textField.endEditing(true)
}
}
}
Using UIPickerview is the right way to go to implement it according to Apple's Human Interface Guidelines
If you select drop down in mobile safari it will show UIPickerview to let the use choose drop down items.
Alternatively
you can use UIPopoverController till iOS 9 as its deprecated but its better to stick with UIModalPresentationPopover of view you want o show as well
you can use UIActionsheet to show the items but it's better to use UIAlertViewController and choose UIActionSheetstyle to show as the former is deprecated in latest versions
I am pretty new to programming and I am trying to insert a picker view. I think my code is right, but when I build the app it is blank. I have no idea what I am doing wrong.
My code is as follows:
import UIKit
class LookingController: UIViewController, UIPickerViewDelegate {
var iama=["dude","lady"]
func numberOfComponentsInPickerView(pickerView: UIPickerView!) ->Int{
return 1
}
func pickerView(pickerView: UIPickerView!, numberOfRowsInComponent component: Int) ->Int {
return iama.count
}
func pickerView(pickerView: UIPickerView!, titleForRow row: Int, forComponent component: Int)->String!{
return iama[row]
}
}
Any suggestions??
I think you forgot to add pickerView into your view so follow this step.
Go to the Storyboard, drag a Picker View from the Object Library to the top of the View Controller inside the Storyboard.
The Storyboard should look like this.
The Picker View must conform to the UIPickerViewDataSource and UIPickerViewDelegate protocol. Ctrl-click the Picker View and drag from the dataSource Outlet to the View Controller in the Document Outline. Repeat this step for the delegate Outlet.
from the reference : http://www.ioscreator.com/tutorials/picker-view-tutorial-ios8-swift
May be this will help you.