I have a fully functional UIPickerView inside a UITableViewCell and would like to accomplish two things.
The UIPickerView displays 4 components, but the first will be seldom referred to. As a result, I would like to either A (preferred) have it display a blank for 0 and scroll to 1, or B modify the color so the 0 is not so dominant.
Secondly, I would like to hide the UIPickerView until selected.
I found both options, but all reside in a UIViewController and do not work within a UITableViewCell.
import UIKit
class DiveDurationTableViewCell: UITableViewCell, UIPickerViewDelegate, UIPickerViewDataSource
{
#IBOutlet var textfieldBizCat: UITextField!
#IBOutlet var pickerBizCat: UIPickerView! = UIPickerView()
// ---------------------------------------------------------------------------------------------
// MARK: - Internal Constant
let numberOfComponents: Int = 4
let FirstDigitComponentRows: Int = 2
let SecondDigitComponentRows: Int = 10
let ThirdDigitComponentRows: Int = 10
let DisplayMinuteComponentRows: Int = 1
let Minutes: String = "Min"
let MinNumber = 0
let MaxNumber = 9
private var diveTime: Array<Int> = [Int]()
var FirstDigit: Int = 0
var SecondDigit: Int = 0
var ThirdDigit: Int = 0
var DisplayMinutes: String = "Min"
// ---------------------------------------------------------------------------------------------
// MARK: - IBOutlets
#IBOutlet var diveTimePicker: UIPickerView!
// ---------------------------------------------------------------------------------------------
// MARK: - UITableVieCell Methods
//
// Called when we are initialized from a storyboard or nib file.
//
override func awakeFromNib()
{
super.awakeFromNib()
//
// We create an array of integers from 0 to 9.
//
for i in self.MinNumber ..< self.MaxNumber+1
{
self.diveTime.append(i)
}
self.diveTimePicker.selectRow(0, inComponent: 0, animated: true)
self.diveTimePicker.selectRow(0, inComponent: 1, animated: true)
self.diveTimePicker.selectRow(0, inComponent: 2, animated: true)
}
//
// The item has been selected in the table.
//
override func setSelected(selected: Bool, animated: Bool)
{
super.setSelected(selected, animated: animated)
}
// ---------------------------------------------------------------------------------------------
// MARK: - UIPickerViewDataSource Methods
//
// Number of components in the picker.
//
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int
{
return self.numberOfComponents
}
//
// Number of rows in each component.
//
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int
{
if component == 0
{
return self.FirstDigitComponentRows
} else if component == 1 {
return self.SecondDigitComponentRows
} else if component == 2 {
return self.ThirdDigitComponentRows
} else {
return self.DisplayMinuteComponentRows
}
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?
{
if component == 0
{
return String(self.diveTime[row])
}
if component == 1
{
return String(self.diveTime[row])
}
if component == 2
{
return String(self.diveTime[row])
}
else
{
return self.DisplayMinutes
}
}
//
// The user has selected in item in the picker view.
//
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
{
}
}
UPDATE:
I am not asking how to create a picker view, as the above code works great. I am only asking how to customize it to make it more attractive.
UITableView is subclass of UIScrollview and UIPicker is scrollview too, you need handle a lot of thing to make both of them work together.
First thing is when you make scroll on UITableview cell with Picker, which one is first response? If Picker is first response and the size of picker is too big such as big as device screen, you will not able to scroll table view anymore. If tableview is first response, you can't scroll Picker because table view will scroll.
I suggest you add Picker View as subview of tableview/controller.view at position/frame of cell that you want to add Picker before, try to fake like Picker inside tableview cell.
Related
The first text field is a Int Value where you insert your current sold. A second one textfield where I get some Int value and add to a tableView with a button. The value you add into the second textfield soustract to the main value ( in that case 2500 ). That's working great.
My problem is to attribuate the PickerValue to the TableRow Value. it's working but not like I want.
I want to save the pickerValue when i click onto the button. But when i enter a new value it's changing all row of the pickerValue. In that case, you can see two row with "telephone". Normaly it's would be "telephone" and something else ( "maison" or "house").
Do you see a reason why it's doing like this ? I wish you can understand what i mean.
problem with picker value save into table view (gif)
#IBAction func addBtn(_ sender: Any) {
view.endEditing(true)
salaire = Int(salaireLabel.text!) ?? 0
valeur = Int(ressourceTextField.text!) ?? 0
if String(valeur) != "" {
addBtnActivated = true
restValueLabel.textColor = UIColor.blue
arrayRessource.append(valeur)
// modifie automatiquement le salaire
restValueLabel.text = String(soustraction)
tableRessourceOT.reloadData()
// reset le champs
ressourceTextField.text = ""
picker.selectRow(0, inComponent: 0, animated: true)
}
}
Here is some code I'm using. I'm thinking the problem came from the tableview Func
var arrayPickerValue: [String] = ["", "maison", "telephone"]
// ------------------------------ START PICKER ------------------------------------
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
print("-----arraypicker.count------")
print(arrayPickerValue.count)
return arrayPickerValue.count
}
// hauteur du picker pour que les images ne se supperpose pas / Picker height
func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
return 25
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
print("----arraypicker[row]----")
print(arrayPickerValue[row])
return arrayPickerValue[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
stored = arrayPickerValue[row]
print("-----stored dans func didselectrow------")
print(stored as Any)
}
//-------------------------- END PICKER -----------------------------------
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let row = indexPath.row
let value = arrayRessource[row]
cell.textLabel?.text = "- " + String(value) + " €"
// cell.detailTextLabel?.text =
updateRestLabel()
setRestLabel()
return cell
}
Here is my outlet :
#IBOutlet weak var tableRessourceOT: UITableView!
Then my arrayRessource :
var arrayRessource: [Int] = [] {
didSet {
if oldValue != arrayRessource {
userDefault.setValue(arrayRessource, forKey: arrayKey)
}
}
}
and call with the function :
func getArray() {
if let newArray = userDefault.array(forKey: arrayKey) as? [Int] {
arrayRessource = newArray
}
}
Your question is not very clear.
However I will make an attempt to offer some help from what I can extract from your code.
I assume restValueLabel is not something within your cells? It is probably the green label "2500" in your screenshot?
If that is the case, don't set it in cellForRow(at:). This method is called every time a cell becomes visible and should only be used to configure that very cell based on your data source (arrayRessource).
Instead create a method updateRestValueLabel() that iterates your data source, does the calculation and sets the appropriate value to your restValueLabel. Call that method every time your data source changes, so along with tableRessourceOT.reloadData().
There are also some stylistic issues with your code (e.g. avoid force unwrapping ! unless you have good reason to use it) but this is out of scope here.
The problem come from my array was an Int array and my pickerValue was String array.
Array can't be String array's and Int array's.
var arrayRessource: [String] = [] {
didSet {
if oldValue != arrayRessource {
userDefault.setValue(arrayRessource, forKey: arrayKey)
}
}
}
Thanx for your advice by the way i'm progressing and doing my best
I have 2 UITableViews in a single View Controller which represent a 23 cells hours table view and 60 cells minutes table view. What i want to achieve is i can scroll both table view like rolling wheel like when we have scrolled to the end, it can still be scrollable to the first table view by scrolling bottom and vice versa.
I found something like this : https://github.com/bharath2020/UITableViewTricks/tree/master/CircleView/BBTableView , but too bad it's in Obj-c.
I want to be able to achieve the following :
Where the hours and minutes can be scrolled infinitely like from 12 -> 0 or 59 -> 0
How do i do something like that in swift?
Okay So just tested out for you. Here is an example for the circular UIPickerView.
import UIKit
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
let maxRows = 10
private let maxElements = 10000
#IBOutlet weak var myPickerView: UIPickerView!
override func viewDidLoad() {
super.viewDidLoad()
self.myPickerView.dataSource = self;
self.myPickerView.delegate = self;
myPickerView.selectRow(maxElements / 2, inComponent: 0, animated: false)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return maxElements
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
let myRow = row % maxRows
let myString = String(format: "%i", myRow)
return myString
}
}
Now as far as creating a UIPickerPickerView with two components is concerned, You can find easily on google.
I hope it helps you to solve the problem.
I'm using a UITableViewCell prototype that contains a UIPickerView and use that prototype for 4 different cells with 4 different PickerView in the tableView. I use the following code to supply the cell to tableView (tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) and to set each picker to a different instance variable in order to differentiate between the pickers later (since the same UITableViewController instance is the delegate/datasource for all of them, for example).
However, when running the code, all 4 instance variables end up pointing to the same UIPickerView. How can I ensure that it uses 4 distinct UIPickerViews instead?
func PickerCell(tableView: UITableView, indexPath: NSIndexPath, inout picker: UIPickerView?) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("PickerCell")
if let pickerFromCell = cell?.contentView.viewWithTag(1) as? UIPickerView {
pickerFromCell.reloadAllComponents()
pickerFromCell.dataSource = self
pickerFromCell.delegate = self
picker = pickerFromCell
}
return cell!
}
Instead of using tag try something like this. Change your didSelectRow of PickerViewDelegate like this
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
let cell = imageView.superview?.superview as! UITableViewCell //You have to use as may super as your UITableViewCell hierarchy
let indexPath = self.tabelView.indexPathForCell(cell)
self.pickerSelectedIndexArr[indexpath.row] = row
}
Also add pickerSelectedIndexArr array in your file and assign it in viewDidLoad like following way
var pickerSelectedIndexArr: [Int] = [Int]()
override func viewDidLoad() {
super.viewDidLoad()
self.pickerSelectedIndexArr = [0, 0, 0 ,0]
}
Now you can easily get all the picker selected value any time you want
Hope this will help you.
var dict: [Int, UIPickerView]
...
if dict[indexPath.row] == nil {
// Create UIPickerView and assign it to dict[indexPath.row].
}
As this question is tagged with Objective C, I am giving your answer in OBJC.
Here is what you can do, to deal with controls in reusable cell,
Tip for solving such problem, when you have controls in UICollectionViewCell or UITableViewCell, give tag to your controls depending upon your indexPath.
Giving example with collectionViewCell you can do it with tableViewCell
case 1 : If CollectionView is sectional, then your tags will be like [0][0], [1][0] ... In such case do something like this,
collectionViewCell.picker.tag = [[NSString stringWithFormat:#"%ld%ld",(long)indexPath.section,(long)indexPath.item] intValue]; // If it is sectional collection view
case 2 : If Collection View is non-sectional,do something like this,
collectionViewCell.picker.tag = [[NSString stringWithFormat:#"%ld",(long)indexPath.item] intValue]; // If it is non-sectional collection view
Hope this will solve your problem or give you idea to manage accordingly.
If you have more than one control in your cell then just give tags like indexPath.item + 1 + 2 ...
I agree with Nirav, that you should use the cell to determine the NSIndexPath of the cell in question.
Personally, I'd make the cell subclass the data source and delegate of the picker and have it take responsibility for the picker. This completely eliminates any confusion about what picker is associated with which cell. But I'd have a protocol by which the cell can inform the view controller when the user selected a value from the picker and the view controller can update the model.
For example, consider this UITableViewCell subclass:
// CustomCell.swift
import UIKit
/// Protocol that the view controller will conform to in order to receive updates
/// from the cell regarding which row in the picker was picked.
///
/// - note: This is a `class` protocol so that I can use `weak` reference.
protocol CustomCellDelegate: class {
func cell(customCell: CustomCell, pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
}
/// Custom cell subclass, which is the picker's data source and delegate
class CustomCell: UITableViewCell, UIPickerViewDataSource, UIPickerViewDelegate {
/// The delegate who we will inform of any picker changes.
///
/// This is weak to avoid strong reference cycle.
weak var delegate: CustomCellDelegate?
/// The array of values to be shown in the picker.
///
/// If the `values` changes, this reloads the picker view.
var values: [String]? {
didSet {
pickerView.reloadComponent(0)
}
}
/// The outlet to the picker in the cell.
#IBOutlet weak var pickerView: UIPickerView!
// MARK: UIPickerViewDataSource
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return values?.count ?? 0
}
// MARK: UIPickerViewDelegate
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return values?[row] ?? ""
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
delegate?.cell(self, pickerView: pickerView, didSelectRow: row, inComponent: component)
}
}
And then the view controller:
// ViewController.swift
import UIKit
class ViewController: UITableViewController, CustomCellDelegate {
// an array of arrays of acceptable values
let troupes = [
["Mo", "Larry", "Curly"],
["Abbott", "Costello"],
["Groucho", "Harpo", "Zeppo", "Chico", "Gummo"],
["Laurel", "Hardy"],
["Graham Chapman", "John Cleese", "Terry Gilliam", "Eric Idle", "Terry Jones", "Michael Palin"]
]
/// An array that indicates which is item is selected for each table view cell
var selectedItemForRow: [Int]!
override func viewDidLoad() {
super.viewDidLoad()
selectedItemForRow = troupes.map { _ in return 0 } // initialize the `selectedItemForRow` array with zeros
// Whatever further initialization of the view controller goes here.
}
// MARK: UITableViewDataSource
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return troupes.count
}
// Populate cell, setting delegate, list of acceptable values, and currently selected value.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CustomCell", forIndexPath: indexPath) as! CustomCell
cell.delegate = self
cell.values = troupes[indexPath.row]
cell.pickerView.selectRow(selectedItemForRow[indexPath.row], inComponent: 0, animated: false)
return cell
}
// MARK: CustomCellDelegate
// When the cell tells us that the user changed the selected row, let's update our model accordingly.
func cell(customCell: CustomCell, pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if let indexPath = tableView.indexPathForCell(customCell) {
selectedItemForRow[indexPath.row] = row
}
}
}
I have followed the following SO question to create multiple picker views.
It works but not exactly how I want it.
What I require:
My view will have multiple buttons. On tap each button will show a picker view at the bottom of the screen.Each buttons picker view will have different options. See image below:
What I have done:
So far I have created two buttons and then added two picker views to my storyboard. See Below
The code is below:
import UIKit
class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
#IBOutlet var one: UIPickerView!
#IBOutlet var Two: UIPickerView!
var picker1Options = [String]()
var picker2Options = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
picker1Options = ["Option 1","Option 2","Option 3","Option 4","Option 5"]
picker2Options = ["Item 1","Item 2","Item 3","Item 4","Item 5"]
self.one.hidden = true
self.Two.hidden = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if (pickerView.tag == 1){
return picker1Options.count
}else{
return picker2Options.count
}
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if (pickerView.tag == 1){
return "\(picker1Options[row])"
}else{
return "\(picker2Options[row])"
}
}
#IBAction func oneShow(sender: AnyObject) {
self.one.hidden = false
}
#IBAction func twoShow(sender: AnyObject) {
self.Two.hidden = false
}
}
The output of the above code is:
The Issues:
As you can see in the above image that although I can show different picker views they are not properly displayed. I would like each picker view to be displayed at the end bottom of the screen.
Also please note that I am using self.picker.hidden = true to hide and unhide the picker views. Is this the correct way of hiding and unhiding picker views? Is there a better way of achieving this functionality?
On the storyboard should I place picker views on top of each other at the bottom of the screen so they always appear at bottom on triggering self.picker.hidden = false ?
Whats the proper way of implementing multiple picker views on storyboard?
Any help will be greatly appreciated.
You make some big concept mistake in the usage of the UiPickerView:
1.You need only one UIPickerView in your storyboard.
2.You need only one data source for the picker view (on button click you gonna change the values in it).
I make an example by your code but be aware there will be some mistakes because i write it on NotePad++ (i don't have Mac in front of me).
class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
#IBOutlet var picker: UIPickerView!
var pickerOptions1 = [String]()
var pickerOptions2 = [String]()
var pickerOptions3 = [String]()
var dataSource;
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
pickerOptions1 = ["Option 1","Option 2","Option 3","Option 4","Option 5"]
pickerOptions2 = ["Item 1","Item 2","Item 3","Item 4","Item 5"]
pickerOptions3 = ["Something 1","Something 2","Something 3","Something 4","Something 5"]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return dataSource.count;
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return "\(dataSiurce[row])"
}
#IBAction func showPickerOne(sender: AnyObject) {
dataSource = pickerOptions1;
[self.picker reloadAllComponents];
}
#IBAction func showPickerTwo(sender: AnyObject) {
dataSource = pickerOptions2;
[self.picker reloadAllComponents];
}
#IBAction func showPickerThree(sender: AnyObject) {
dataSource = pickerOptions3;
[self.picker reloadAllComponents];
}
}
I hope this will help you understand the concept of pickers in ios.
You can take textfield instead of buttons and add picker view as inputview of textfield. And based on the textfield you can change the contents of array and displayed in pickerview.
Please find image in that i used age picker and team picker.
EDIT:
-(void) viewWillAppear:(BOOL)animated
{
[self.PickerVw removeFromSuperview];
txtAge.inputView = self.PickerVw;
txtSportName.inputView = self.PickerVw;
}
#pragma mark - UItextfield delegate Methods
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
arr1 = [NSMutableArray new];
if (textField.tag == 1)
{
int min = 9;
int max = 100;
for (int i = min ; i < max; i++)
{
[arr1 addObject:[NSString stringWithFormat:#"%d",(i+1)]];
}
[textField becomeFirstResponder];
self.picker.tag = 1;
}
if (textField.tag == 2)
{
[self.picker selectRow:0 inComponent:0 animated:NO];
arr1 = [arrSports mutableCopy];
[textField becomeFirstResponder];
self.picker.tag = 2;
}
[self.picker reloadAllComponents];
}
Here's a sample code on how Apple shows/hides a datePicker which should point you to the right direction.
I have a ViewController with a UIPickerView as a single control myPickerView which is of a class MyPickerView which I created as a sub-class of UIPickerView. I invoke myPickerView in ViewController viewDidLoad by myPickerView.viewDidLoad. However, this does not execute the source functions of MyPickerView.
I need a clarification of how I can make this work. My reason for MyPickerView is that it has a lot of special code that I did not want to clutter up the main ViewController. See the example code below:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var myPickerView: MyPickerView!
override func viewDidLoad() {
super.viewDidLoad()
myPickerView.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
import UIKit
var gSep = ","
class MyPickerView: UIPickerView , UIPickerViewDataSource, UIPickerViewDelegate {
var pickerData = [[" "],[" "]]
var category = [""]
var subCategory = [""]
var dictMenuList = [String:String]()
//MARK:- category/subcategory picker
func viewDidLoad() {
println("MyPickerView: viewDidLoad")
dictMenuList = ["Medical":"Sub-Cat 1.1,Sub-Cat 1.2,Sub-Cat 1.3,Sub-Cat 1.4,Sub-Cat 1.5,Sub-Cat 1.6,Sub-Cat 1.7",
"Taxes": "Sub-Cat 2.1,Sub-Cat 2.2,Sub-Cat 2.3,Sub-Cat 2.4",
"Bills": "Sub-Cat 3.1,Sub-Cat 3.2,Sub-Cat 3.3,Sub-Cat 3.4,Sub-Cat 3.5,Sub-Cat 3.6,Sub-Cat 3.7"]
println("MyPickerView dictMenuList: \(dictMenuList)")
self.reloadAllComponents()
let firstKey = self.loadPickerWithCategory(0)
self.loadPickerWithSubCategory(firstKey)
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
println("MyPickerView: numberOfComponentsInPickerView \(pickerData.count)")
return pickerData.count
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerData[component].count
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if component == 0 {
let selectedKey = category[row]
loadPickerWithSubCategory(selectedKey)
}
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return pickerData[component][row]
}
func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView!) -> UIView
{
var pickerLabel = UILabel()
pickerLabel.textColor = UIColor.blackColor()
pickerLabel.text = pickerData[component][row]
pickerLabel.font = UIFont(name: pickerLabel.font.fontName, size: 17)
pickerLabel.textAlignment = NSTextAlignment.Center
return pickerLabel
}
func loadPickerWithCategory (row: Int) -> String{
println("loadPickerWithCategory")
category = [String](dictMenuList.keys)
println("MyPickerView: category: \(category)")
if category.isEmpty {
return ""
}
let n1 = dictMenuList.count
pickerData[0].removeAll(keepCapacity: true)
for i in 0 ..< n1
{
pickerData[0].append(category[i])
}
return category[row]
}
func loadPickerWithSubCategory (key: String) {
println("MyPickerView: loadPickerWithSubCategory")
let x = dictMenuList[key]
subCategory = x!.componentsSeparatedByString(gSep)
let n1 = subCategory.count
pickerData[1].removeAll(keepCapacity: true)
if subCategory.isEmpty {
return
}
for i in 0 ..< n1
{
pickerData[1].append(subCategory[i])
}
self.reloadAllComponents()
}
}
The method viewDidLoad is a view controller method, not a view method. A UIPickerView is a subclass of UIView, not UIViewController, so the system will not call your viewDidLoad method.
You need to override one or more of the init methods.
If you're loading your picker view from a Storyboard or XIB, you probably want to override initWithCoder.
If you're creating your picker in code, you probably want to override initWithFrame.
I sometimes create a method setup that I call from both initWithCoder: and from initWithFrame:. That way my setup code gets called regardless of how the view object is loaded.
I vaguely remember reading that there is a better way of handling this dueling initializers problem in Swift, but I don't remember what it is. (I'm still learning Swift.)
EDIT:
It just occurs to me that you can use the method awakeFromNib to do setup after your view has been loaded and all of it's outlets are set up. That's roughly equivalent to the viewDidLoad call for view controllers. I should have thought of that sooner.
(awakeFromNib is a method of NSObject, so it's a bit hard to find if you don't know it exists.)
First of all viewDidLoad() is a method of the UIViewController class and is called after the controller's view is loaded into the memory. Read more here. You can not use it in views.
So you should implement an init method inside your custom picker class. I'd recommend to override initWithFrame and initWithCoder and set up your component there.
And you will initialize your custom picker like this:
myPickerView = MyPickerView(frame: yourFrame)