UIPickerView and UISearchController not displaying data - ios

I am experiencing some trouble at the moment and was hoping one of the experts could assess and hopefully answer my question. I have made a UIPickerView and a UISearchController (which is in a UITableViewController) and both of which have no been showing the data from the arrays I made. This is a school project and is not due till Tuesday, but I am hoping I can fix these small (hopefully bugs). I will show you my ViewControllers for both the UIPickerView and the UISearchController.
So here is the UIPickerView :
import UIKit
class SecondViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, UITextFieldDelegate {
#IBOutlet weak var txtTest: UITextField!
#IBOutlet weak var Picker1: ThePickerView!
var sellInvestments = ["Airbnb", "CloudFlare", "GitHub", "slack", "Snapchat", "Uber"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.Picker1.delegate = self
self.Picker1.dataSource = self
[self.Picker1.reloadAllComponents]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func pickerView(_pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return sellInvestments[row]
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return sellInvestments.count
}
public func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
}
And now here is the UITableViewController (for the UISearch)
import UIKit
class NewTableViewController: UITableViewController, UISearchResultsUpdating {
let searchInvestments = ["Berlark Company", "Snapchat", "IBM", "Twitter", "Cornerstone on Demand", "Aukvern Capital", "Serene Technologies", "Viacom Industries", "Suvertec", "HIppit", "Avigti Technologies", "Avaret", "Sivlot", "Zebra Sci Automation", "Google", "Apple", "Facebook", "Gradience Imaging", "Vitris", "Voxtrat", "WhattsApp", "Apphat", "Nividia", "Kik", "Cyber Dust", "Turing Technologies", "Sobel Imaging Systems", "Yavid", "Tensor Automation", "Vistapint", "LinkedIn", "Yahoo", "Yelp", "TwitchTv", "OculusRift", "Lg", "Intel", "Amazon", "Sony", "Samsung", "Microsoft", "HP", "Vencore", "AT&T", "Verizon", "Dell", "MicroTech", "Flickr"]
var filteredInvestments = [String]()
var resultSearchController = UISearchController()
override func viewDidLoad() {
super.viewDidLoad()
self.resultSearchController = UISearchController(searchResultsController: nil)
self.resultSearchController.searchResultsUpdater = self
self.resultSearchController.dimsBackgroundDuringPresentation = false
self.resultSearchController.searchBar.sizeToFit()
self.tableView.tableHeaderView = self.resultSearchController.searchBar
self.tableView.reloadData()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
if self.resultSearchController.isActive
{
return self.filteredInvestments.count
}
else {
return self.searchInvestments.count
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as UITableViewCell?
if self.resultSearchController.isActive
{
cell!.textLabel?.text = self.filteredInvestments[indexPath.row]
}
else {
cell!.textLabel?.text = self.searchInvestments[indexPath.row]
}
return cell!
}
func updateSearchResults(for searchController: UISearchController) {
self.filteredInvestments.removeAll(keepingCapacity: false)
let searchPredicate = NSPredicate(format: "SELF CONTAINS[c] %#", searchController.searchBar.text!)
let array = (self.filteredInvestments as NSArray).filtered(using: searchPredicate)
self.filteredInvestments = array as! [String]
self.tableView.reloadData()
}
}
OK so there is the code of both the PickerView and Search view.
*There are no compiling errors and the app does run. I have it hooked up to my iPhone 5c and am able to run the app nicely.
Here are some pictures of the app running. (With the unfilled views)
here are the links to the images (because I don't have a 10 reputation)
http://imgur.com/a/0Gp4P - PickerView
http://imgur.com/a/JiUFe - UISearch
Thank you so much if you are able to answer this, because I have looked around the web and most of the time there was little to no help, and the ones with help, turned out not to do anything. So to summarize, the strings I put into my arrays are not showing up on either when I run it.
Thank you Very Much guys!

For your UIPickerView you forgot the function:
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView
{
let pickerLabel = UILabel() //Create label
pickerLabel.textColor = UIColor.black //Create text color
pickerLabel.text = pickerData[row] //Make text for row the one in array
pickerLabel.font = UIFont(name: "Helvetica-Light", size: 20) //Text font
pickerLabel.textAlignment = NSTextAlignment.center //Alignment
return pickerLabel
}
As for the search, use a similar function as above, just without the picker view it will be for search view. Autocomplete should help find it.

Related

Cannot convert return expression of type 'NSManagedObject' to return type 'String?'

I have built an app (my first) and it works like I want it to, but then I needed to add CoreData to it to get my events saved/fetched. I can see that my events (add information to tableview/remove information from there) gets saved as I print it, and the app is "Loaded" in "viewDidAppear".
The problem I think is that I am saving the array, not the NSobject. OR I am fetch the array, not the NSobject? I believe what I need to do is to add my array to an NSManagedObject?
Like this:
var List:[MealsMenu] = [].
When I do this I get it to work! Thats great! BUT, I have an VC that is calling this variable in a UIPickerView, and as soon as I Add the list to NSManagedObject (MealsMenu, which is my Entity in coredatamodel) I get this error-message:
Cannot convert return expression of type 'NSManagedObject' to return type 'String?'
I have tried to google this for a few days now but can't find any solution for this in my case. Do any of you have any idea what I can do?
My Entity (MealsMenu) have an attribute called "meals" which is refer to String.
As I said, If I skip the VC where the PickerView is I get it to work! Added and Deleted events are being saved.
Here are my code:
(All places where it says "List[row]" or "List[indexPath.row]" I get this error message).
addViewController:
import UIKit
import CoreData
class addViewController: UIViewController, UITextFieldDelegate {
var context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
#IBOutlet weak var input: UITextField!
#IBAction func addToMenu(_ sender: Any) {
if input != nil{
let newMeal = NSEntityDescription.insertNewObject(forEntityName: "MealsMenu", into: context)
newMeal.setValue(self.input.text, forKey: "meals")
do {
try context.save()
print("SAVED")
}
catch{
print(error)
}
input.text = ""
}else{
print("That's not a meal!")
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
input.resignFirstResponder()
return true
}
}
tableViewController:
import UIKit
import CoreData
class tableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (List.count)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
cell.textLabel?.text = List[indexPath.row]
cell.textLabel?.textColor = UIColor.white
cell.backgroundColor = UIColor.clear
return(cell)
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == UITableViewCell.EditingStyle.delete
{
List.remove(at: indexPath.row)
myTableView.reloadData()
}
}
#IBOutlet weak var myTableView: UITableView!
override func viewDidAppear(_ animated: Bool) {
myTableView.reloadData()
}
override func viewDidLoad() {
super.viewDidLoad()
coredataClass.saveItems()
coredataClass.loadData()
}
}
ViewController:
import UIKit
import CoreData
var List:[MealsMenu] = []
class ViewController: UIViewController {
#IBOutlet weak var monday: UITextField!
#IBOutlet weak var tuesday: UITextField!
#IBOutlet weak var wednesday: UITextField!
#IBOutlet weak var thursday: UITextField!
#IBOutlet weak var friday: UITextField!
#IBOutlet weak var saturday: UITextField!
#IBOutlet weak var sunday: UITextField!
var daysArray = [UITextField]()
let pickerView = ToolbarPickerView()
var selectedMenu : String?
override func viewDidLoad() {
super.viewDidLoad()
setupDelegateForPickerView()
setupDelegatesForTextFields()
coredataClass.loadData()
}
func setupDelegatesForTextFields() {
//appending textfields in an array
daysArray += [monday, tuesday, wednesday, thursday, friday, saturday, sunday]
//using the array to set up the delegates, inputview for pickerview and also the inputAccessoryView for the toolbar
for day in daysArray {
day.delegate = self
day.inputView = pickerView
day.inputAccessoryView = pickerView.toolbar
}
}
func setupDelegateForPickerView() {
pickerView.dataSource = self
pickerView.delegate = self
pickerView.toolbarDelegate = self
}
}
// Create an extension for textfield delegate
extension ViewController : UITextFieldDelegate {
func textFieldDidBeginEditing(_ textField: UITextField) {
self.pickerView.reloadAllComponents()
}
}
// Extension for pickerview and toolbar
extension ViewController : UIPickerViewDelegate, UIPickerViewDataSource {
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return List.count
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return List[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
// Check if the textfield isFirstResponder.
if monday.isFirstResponder {
monday.text = List[row]
} else if tuesday.isFirstResponder {
tuesday.text = List[row]
} else if wednesday.isFirstResponder {
wednesday.text = List[row]
} else if thursday.isFirstResponder {
thursday.text = List[row]
} else if friday.isFirstResponder {
friday.text = List[row]
} else if saturday.isFirstResponder {
saturday.text = List[row]
} else if sunday.isFirstResponder {
sunday.text = List[row]
} else {
//log errors
}
}
}
extension ViewController: ToolbarPickerViewDelegate {
func didTapDone() {
self.view.endEditing(true)
}
func didTapCancel() {
self.view.endEditing(true)
}
}
Specific these functions/lines in "ViewController" are throwing theses errors:
Cannot convert return expression of type 'MealsMenu' to return type 'String?'
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return List[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
// Check if the textfield isFirstResponder.
if monday.isFirstResponder {
monday.text = List[row]
} else if tuesday.isFirstResponder {
tuesday.text = List[row]
} else if wednesday.isFirstResponder {
wednesday.text = List[row]
} else if thursday.isFirstResponder {
thursday.text = List[row]
} else if friday.isFirstResponder {
friday.text = List[row]
} else if saturday.isFirstResponder {
saturday.text = List[row]
} else if sunday.isFirstResponder {
sunday.text = List[row]
} else {
//log errors
}
}
And in "tableViewController" this function is throwing a similar error:
Cannot assign value of type 'MealsMenu' to type 'String?'
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
cell.textLabel?.text = List[indexPath.row]
cell.textLabel?.textColor = UIColor.white
cell.backgroundColor = UIColor.clear
Thanks a lot for any guidens and help!
/
Andreas
Please read the error message carefully and then have a look at you design
Your data source is an array of MealsMenu instances which is a subclass of NSManagedObject while the return value is of type String?.
That's what the error message says: You cannot return a MealsMenu instance where a string is expected
return List[row].meals
There are two bad practices in the data source declaration line.
Variable names are supposed to be named lowercased.
The variable name of an array is supposed to be named in plural form.
The latter would indicate clearly that the variable contains multiple items for example
var menus : [MealsMenu] = []
With this change and with splitting the line into two the error becomes more obvious
let menu = menus[row]
return menu.meals
By the way the naming meals is also confusing because it implies to be an array.
In cellForRow change the lines accordingly
let menu = menus[indexPath.row]
cell.textLabel?.text = menu.meals

UIPickerView inside a Custom UITableViewCell not initialising, awakeFromNib() not being called

I'm trying to get a UIPickerView inside a custom UITableViewCell to load. The cell loads fine, and I'm able to pass the data (an array of strings) from the UITableViewController to the custom cell through a delegate but the picker just loads blank. I can't for the life of me figure out why.
This seems to be a similar issue but the suggested solution (namely to reload the components of the UIPickerView after setting the pickerData array in the cellForRowAt method) doesn't seem to work.
Any help or insights greatly appreciated.
Custom Cell with UIPickerView
class GradeSelectionCell: UITableViewCell, UIPickerViewDataSource, UIPickerViewDelegate, ReusableView {
#IBOutlet var pickerView: UIPickerView!
var pickerData = [String]()
var numComponents = Int()
override func awakeFromNib() {
// Initialization code
self.pickerData = Array<String>()
self.pickerView.delegate = self
self.pickerView.dataSource = self
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return numComponents
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerData.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
print(pickerData[row])
return pickerData[row]
}
}
extension GradeSelectionCell: PickerSetupDelegate {
func setupPicker(data: [String], numberOfCompents: Int){
pickerData = data
numComponents = numberOfCompents
print("PickerSetupDelegate Called")
print("pickerData \(String(describing: pickerData))")
}
}
cellForRowAt
let cell = tableView.dequeueReusableCell(withIdentifier: "GradeSelectionCell", for: indexPath) as! GradeSelectionCell
cell.setupPicker(data: grades, numberOfCompents: 1)
// cell.pickerView.reloadAllComponents()
return cell
Registering Cell in viewDidLoad
tableView.register(GradeSelectionCell.self, forCellReuseIdentifier: "GradeSelectionCell")
You're registering the cell using the cell class initializer:
func register(_ cellClass: AnyClass?, forCellReuseIdentifier identifier: String)
But it seems you're trying initialize the cell from a xib. So you should be using the UINib initializer:
func register(_ nib: UINib?, forCellReuseIdentifier identifier: String)
e.g.
tableView.register(UINib(nibName: "GradeSelectionCell", bundle: nil), forCellReuseIdentifier: "GradeSelectionCell"))
(or whatever the filename of the xib you're using is).
Otherwise, you're just loading an instance of the class directly without the user interface you laid out in the xib.
Note, if you're using a cell defined in a storyboard in your controller's view, then it would already be registered and you do not need to register it again.
And it's not crashing because you're never actually calling the pickerView property — awakeFromNib won't be called, and setupPicker just sets data. Presumably it crashes when you uncomment the line cell.pickerView.reloadAllComponents()?

reloaddata() function closes tableview, and returns to be previous screen

I have an app with two screens (view controller and tableview) I am trying to reload data in my table view each time user updates a filter used on the data. For example, my array holds train schedule data, I filter this data based on direction. The user updates the direction and then the tableview should reload based and update filter for direction.
I have tried to use
DispatchQueue.main.async { self.tableView.reloadData() }
I have function that is called by a button action to update direction
#IBAction func ChangeDirection(_ sender: Any) {
changeDirection()
}
func changeDirection()
{
if direction == "Southbound" {
direction = "Northbound"
}
else {
direction = "Southbound"
}
DispatchQueue.main.async { self.tableView.reloadData() }
}
I use view controller with ui picker so user can select station they want train schedule on, the ui picker accesses a singleton class that holds the train scheduled data for each station (I am wondering if this maybe the issue) maybe this needs to be accessed from tableview.
if segue.identifier == "Stations"
{
let vc = segue.destination as? TableViewController
let xmlParserSchedule = XMLParserSchedule()
xmlParserSchedule.runScheudledParser(userStation:StationsDecoder.shared.uiStationsSorted[station])
vc?.stationData=xmlParserSchedule.sortedArrival
}
I expect the tableview to reload based on new direction selected by the user, however tableview is closed and we go back to view controller ui picker screen. When I debug step into code when calling reloaddata() I have noted the memory seems to leak infinitely.
I am adding complete code from viewcontroller and table view incase this is helpful:
view controller:
import UIKit
#available(iOS 9.0, *)
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
//stores picker selection for array index in station data
var station = 0
//UI Picker Outlet
#IBOutlet weak var UIStationPicker: UIPickerView!
override func viewDidLoad() {
super.viewDidLoad()
//self.UIStationPicker.setValue(UIColor.white, forKey: "textColor")
self.UIStationPicker.delegate = self
self.UIStationPicker.dataSource = self
self.UIStationPicker.reloadAllComponents()
//check if station file is already loaded by accessing the singletons/create plist throw method
do {
try? CreatePlist.shared.createPlist()
//throw needed here to reach the catch block
throw CreatePlist.ErrorsToThrow.fileAlreadyExists
}catch {
print("file already exists")
print("time to get decoding")
//decode the station plist using singleton class method
StationsDecoder.shared.decoder()
//get stations in array of dictionaries using singlton class method
StationsDecoder.shared.getStations()
self.UIStationPicker.reloadAllComponents()
}
}
//uiPicker delegate methods
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Number of columns of data
}
func numberOfComponents(in pickerView: UIPickerView) ->Int {
return 1
}
// The number of rows of data
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int)-> Int {
return StationsDecoder.shared.uiStationsSorted.count
}
// The data to return for the row and component (column) that's being passed in
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int)-> String? {
return StationsDecoder.shared.uiStationsSorted[row]
}
func pickerView(_ pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? {
let titleData = StationsDecoder.shared.uiStationsSorted[row]
let myTitle = NSAttributedString(string: titleData, attributes: [NSAttributedString.Key.font:UIFont(name: "Georgia", size: 28.0)!,NSAttributedString.Key.foregroundColor:UIColor.white])
return myTitle
}
// Capture the picker view selection
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
station = row
performSegue(withIdentifier: "Stations", sender: Any?.self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?){
if segue.identifier == "Stations"
{
let vc = segue.destination as? TableViewController
let xmlParserSchedule = XMLParserSchedule()
xmlParserSchedule.runScheudledParser(userStation:StationsDecoder.shared.uiStationsSorted[station])
vc?.stationData=xmlParserSchedule.sortedArrival
}
}
}
tableview
import UIKit
var direction:String = "Southbound"
class TableViewController: UITableViewController{
//this code here is interesting, it dismisses the presented view with orignally presented view ie tableview is replaced with initial view controller. this avoids calling dataload method again in view controller which can duplicate your data
#IBAction func GoBack(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
#IBAction func ChangeDirection(_ sender: Any) {
changeDirection()
}
func changeDirection()
{
if direction == "Southbound" {
direction = "Northbound"
}
else {
direction = "Southbound"
}
DispatchQueue.main.async { self.tableView.reloadData() }
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
//array of tuples to hold station data
var stationData: [(stationfullname:String,origin: String,destination:String,lastLocation: String, dueIn: Int, late: Int, due: Int, expArrival: String, direction: String) ] = []
//array literal, for tuples
//var data = [String:(stationfullname:String,origin: String,destination:String,lastLocation: String, dueIn: Int, late: Int, due: Int, expArrival: String, direction: String)].self
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// As long as `total` is the last case in our TableSection enum,
// this method will always be dynamically correct no mater how many table sections we add or remove.
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return stationData.filter{($0.direction == direction)}.count
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return direction
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "StationLevel", for: indexPath)
cell.textLabel?.text = stationData.filter{($0.direction == direction)}[indexPath.row].destination
cell.detailTextLabel?.text = "\(String(stationData.filter{($0.direction == direction)}[indexPath.row].due)) mins"
return cell
}
}
Oh Lordie,turns out I had an extra sent event for the button that was sending back to view controller, there is 4 hours I will never get back.
Thanks for the help regardless Parvin.

How to initialize UiPickerView inside custom tableViewCell?

I am trying to create PickerView inside tableViewCell. I made my custom cell conform UIPickerViewDelegate and UIPickerViewDataSource protocols. I send data array to cell from the controller (I think this doesn't conform to MVC pattern, may be you also can suggest me how to fix that?). But when tableview calls dequeueReusableCellWithIdentifier the cell calls pickerView function. However, pickerView function uses pickerData which is not initialized yet. How do I fix that?
Below is my code for the cell:
class PickerTableViewCell: UITableViewCell, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var picker: UIPickerView!
#IBOutlet weak var title: UILabel!
var pickerData: Array<String>!
override func awakeFromNib() {
self.picker.delegate = self;
self.picker.dataSource = self;
super.awakeFromNib()
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerData.count // I get fatal error here due to pickerData is nil
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return pickerData[row]
}
}
And here is the code for the cell's initialization:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("picker", forIndexPath: indexPath) as! PickerTableViewCell
cell.title.text = fieldModel.editFieldArray[indexPath.row].title
cell.pickerData = (fieldModel.editFieldArray[indexPath.row] as! PickerEditField).pickerData
return cell
}
Thanks a lot for any help!
Your issue is that you have reload the components of PickerView so make one small change in your cellForRowAtIndexPath and just reload the components of PickerView after setting the pickerData Array.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("picker", forIndexPath: indexPath) as! PickerTableViewCell
cell.title.text = fieldModel.editFieldArray[indexPath.row].title
cell.pickerData = (fieldModel.editFieldArray[indexPath.row] as! PickerEditField).pickerData
cell.picker.reloadAllComponents();
return cell
}
Also in awakeFromNib initialize your pickerData object
override func awakeFromNib() {
self.pickerData = Array<String>()
self.picker.delegate = self;
self.picker.dataSource = self;
super.awakeFromNib()
}

Swift - Programmatically create and display UIPickerView when BarButtonItem is pressed

Initially I wanted to add a hidden UIPickerView onto the Main.storyboard alongside my existing UISearchBar and when a BarButtonItem is clicked, the UIPickerView should be displayed; but it appears I cannot have them both at once in a given space.
So instead, my best alternative was to create it programmatically. I've followed existing tutorials (http://sourcefreeze.com/ios-uipickerview-example-using-swift/) and similar questions (Programmatically Create and Show UIPickerView) and seems like I do (?) have a UIPickerView as the description of it is being printed and I get the following:
<UIPickerView: 0x7f86425b1fb0; frame = (100 100; 100 162); layer = <CALayer: 0x7f8642543a20>>
Here is part of my current code which may be of help:
AnimalTableViewController.swift
import UIKit
class AnimalTableViewController: UITableViewController, UINavigationControllerDelegate, UISearchBarDelegate, UISearchDisplayDelegate, UISearchResultsUpdating, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet var segmentedSortOption: UISegmentedControl!
var array : NSArray = Animal.animalStruct.jsonResult["animal"] as NSArray
var filteredArray = [[String:AnyObject]]()
var timer = NSTimer()
var counter:Int = 1
var typePickerView: UIPickerView = UIPickerView()
#IBOutlet var typeBarButton: UIBarButtonItem!
var resultSearchController = UISearchController()
var indexArray:String!
#IBAction func refresh(sender: AnyObject) {
self.tableView.reloadData()
println("refreshed")
}
override func viewDidLoad() {
super.viewDidLoad()
self.typePickerView.hidden = true
self.typePickerView.dataSource = self
self.typePickerView.delegate = self
self.typePickerView.frame = CGRectMake(100, 100, 100, 162)
self.typePickerView.backgroundColor = UIColor.blackColor()
self.typePickerView.layer.borderColor = UIColor.whiteColor().CGColor
self.typePickerView.layer.borderWidth = 1
timer = NSTimer.scheduledTimerWithTimeInterval(0.2, target: self, selector: Selector("result"), userInfo: nil, repeats: true)
self.resultSearchController = ({
let controller = UISearchController(searchResultsController: nil)
controller.searchResultsUpdater = self
controller.dimsBackgroundDuringPresentation = false
controller.searchBar.sizeToFit()
self.tableView.tableHeaderView = controller.searchBar
return controller
})()
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return array.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return array[row]["type1"] as String
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
typeBarButton.title = array[row]["type1"] as? String
typePickerView.hidden = false
}
func pickerView(pickerView: UIPickerView, widthForComponent component: Int) -> CGFloat {
return 36.0
}
func pickerView(pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
return 36.0
}
#IBAction func typePickerViewSelected(sender: AnyObject) {
typePickerView.hidden = false
println(typePickerView.description)
}
}
Please could you help me display the programmatically created UIPickerView when the BarButtonItem is pressed? If you have any more questions, please do ask.
Many thanks.
You never add the pickerView as a subview of the ViewController, which you can do in viewDidLoad() since you're hiding it. Then when you unhide it your view should be there.
EDIT: Added Code
override func viewDidLoad() {
super.viewDidLoad()
self.typePickerView.hidden = true
//other pickerView code like dataSource and delegate
self.view.addSubview(pickerView) //will add the subview to the view hierarchy
}
With the above code, now when you unhide it on button press the view will show up.

Resources