Get the uipickerview value from a .xib file - ios

I am very new to Swift (less than one week) I create a table view where I have more cells , each cell gets create from a .xib file, and the fields get populated because I create an array of objects that are used in order to populate the cells.
I have a file called: MenuWeekViewControoler.swift where I have the tableView.
I have a file called FoodTableViewCell.swift which is connected with the .xib file
Inside the FoodTableViewCell I have the uipickerview and in the MenuWeekViewControoler I visualise the pickerview and interact with it.
My wish is to get the value of the picker view for each separate cell and I don't really know how to do it.
I will attach the code of the 3 files in order for the code to make sense:
MenuWeekViewControoler :
import UIKit
class MenuWeekViewController : UIViewController, UITableViewDelegate, UITableViewDataSource {
var menus : [Menu] = [
Menu(nameMenu: "BBQ", priceMenu: 8, pickerDada: ["0","1","2","3","4","5","6","7","8","9","10"]),
Menu(nameMenu: "BBQ2", priceMenu: 8, pickerDada: ["0","1","2","3","4","5","6","7","8","9","10"]),
Menu(nameMenu: "BBQ3", priceMenu: 8, pickerDada: ["0","1","2","3","4","5","6","7","8","9","10"]),
Menu(nameMenu: "BBQ4", priceMenu: 8, pickerDada: ["0","1","2","3","4","5","6","7","8","9","10"]),
Menu(nameMenu: "BBQ4", priceMenu: 8, pickerDada: ["0","1","2","3","4","5","6","7","8","9","10"]),
Menu(nameMenu: "BBQ4", priceMenu: 8, pickerDada: ["0","1","2","3","4","5","6","7","8","9","10"]),
]
var test = FoodTableViewCell()
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var nameSection: UITextField!
#IBOutlet weak var privateGuestsUIPicker: UIPickerView!
#IBOutlet weak var BusinessGuestUIPicker: UIPickerView!
#IBOutlet weak var commentSection: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
tableView.rowHeight = 100
tableView.register(UINib(nibName: "FoodTableViewCell", bundle: nil), forCellReuseIdentifier: "ReusableMenuCell")
}
#IBAction func updateOrders(_ sender: UIButton) {
}
#IBAction func sendOrder(_ sender: UIButton) {
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return menus.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ReusableMenuCell", for: indexPath) as! FoodTableViewCell
cell.menuName?.text = menus[indexPath.row].nameMenu
cell.priceMenu?.text = String("\(menus[indexPath.row].priceMenu) CHF")
return cell
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
print(menus[indexPath.row].nameMenu)
}
}
FoodTableViewCell :
import UIKit
class FoodTableViewCell: UITableViewCell,UIPickerViewDelegate, UIPickerViewDataSource {
var pickerDada = ["0","1","2","3","4","5","6","7","8","9","10"]
#IBOutlet weak var quantityMenu: UIPickerView!
#IBOutlet weak var priceMenu: UILabel!
#IBOutlet weak var menuName: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
quantityMenu.dataSource = self
quantityMenu.delegate = self
quantityMenu.setValue(UIColor.white, forKey: "textColor")
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return 11
}
internal func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return pickerDada[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
{
print(pickerDada[row])
}
}
Menu struct :
import UIKit
struct Menu{
var nameMenu : String
var priceMenu : Int
var pickerDada : [String] = [String]()
}
Thank you to everyone willing to help

in FoodTableViewCell you should define a delegate protocol
and define it as a variable such as:
import UIKit
protocol FoodCellDelegate: AnyObject {
func tapFood(food: YourFoodModel) or // func tapFood(food: pickerDada) or whatever you want pass it
}
class FoodTableViewCell: UITableViewCell,UIPickerViewDelegate, UIPickerViewDataSource {
//define a variable type of delegate
weak var delegate: FoodCellDelegate?
.
.
.
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
{
print(pickerDada[row])
// add this
delegate?.tapFood(food: pickerData[row])
}
}
after that you must delegate it to your MenuWeekViewController:
class MenuWeekViewController : UIViewController, UITableViewDelegate, UITableViewDataSource {
.
.
.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ReusableMenuCell", for: indexPath) as! FoodTableViewCell
cell.menuName?.text = menus[indexPath.row].nameMenu
cell.priceMenu?.text = String("\(menus[indexPath.row].priceMenu) CHF")
// add this
cell.delegate = self
return cell
}
.
.
.
}
extension MenuWeekViewController: FoodCellDelegate {
func tapFood(food: YourFoodModel) {
print it
}
}

Related

Using multiple UIPickerViews in dynamic UITableView

I am trying to make use of UIPickerViews, whereby the user can select an "amount"(number) between 1 and 20. In my TableviewCell there is a label and the picker.
Before I implemented the PickerViewDelegate and PickerViewDatasource, everything was fine. Since then I cannot even check if my code is right, cause it gives me "Fatal error: Unexpectly found nil..." for the label which has the array soloJobs (Array is not empty). So I guess I am making something fundamentally wrong.
At the end my achievment would be to store the values of the jobAmountPickerin the selAmountArray for given index.
Maybe someone can help.
This is my tableviewcell:
import UIKit
var globalAmount:[String] = []
class ProjectCharacterTableViewCell: UITableViewCell, UIPickerViewDelegate, UIPickerViewDataSource {
var jobAmount: [String] = []
var pickerData = ["1", "2", "3", "4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20"]
var selAmountArray: [String] = []
static let identifier = "ProjectCharacterTableViewCell"
#IBOutlet weak var jobLabel: UILabel!
#IBOutlet weak var jobAmountPicker: UIPickerView!
override func awakeFromNib() {
self.pickerData = Array<String>()
self.jobAmountPicker.delegate = self;
self.jobAmountPicker.delegate = 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
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
let selectedAmount = pickerData[row] as String
selAmountArray.append(selectedAmount)
globalAmount = selAmountArray
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return pickerData[row]
}
}
And that's my viewController:
import UIKit
import FirebaseDatabase
import Foundation
import FirebaseFirestoreSwift
import CodableFirebase
class ProjectCharacterViewController: UIViewController, UITextFieldDelegate {
// MARK: - Properties
#IBOutlet weak var specTxt: UITextField!
#IBOutlet weak var difficultyTxt: UITextField!
#IBOutlet weak var budgetTxt: UITextField!
#IBOutlet weak var tableView: UITableView!
var soloJobs: [String] = []
var jobAmount: [String] = []
var rowBeingEditet : Int? = nil
var indexesNeedPicker: [NSIndexPath]?
var i: Int?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
getJobs(for: User.current) { (memberJob) in
}
}
override func viewDidLoad() {
tableView.register(ProjectCharacterTableViewCell.self, forCellReuseIdentifier: "ProjectCharacterTableViewCell")
super.viewDidLoad()
}
// MARK: - Functions
func getJobs(for user: User, completion: #escaping ([MemberJobsStruct]) -> Void) {
var jobs: [String] = []
let ref = Database.database().reference().child("team").child(user.uid)
ref.observe(DataEventType.value, with: { snapshot in
for case let child as DataSnapshot in snapshot.children {
guard let value = child.value as? [String: Any] else {
return completion ([])
}
let memberJob = value["memberJob"] as! String
jobs.append(memberJob)
self.soloJobs = self.removeDuplicates(array: jobs)
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
})
}
func removeDuplicates(array: [String]) -> [String] {
var encountered = Set<String>()
var result: [String] = []
for value in array {
if encountered.contains(value) {
// Do not add a duplicate element.
}
else {
// Add value to the set.
encountered.insert(value)
// ... Append the value.
result.append(value)
}
}
return result
}
#IBAction func show(_ sender: Any) {
print("SoloJobs: ", soloJobs)
print("Thats the job amount: ", jobAmount)
print("Global amount :", globalAmount)
}
}
// MARK: - UITableViewDataSource
extension ProjectCharacterViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return soloJobs.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ProjectCharacterTableViewCell") as! ProjectCharacterTableViewCell
cell.jobLabel.text = soloJobs[indexPath.row]
i = indexPath.row
cell.jobAmountPicker.reloadAllComponents();
return cell
}
}
// MARK: - UITableViewDelegate
extension ProjectCharacterViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 60
}
}

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

Setting a delegate to an outlet in a class without an initialiser

I am trying to assign a delegate to a pickerView outlet in a class with a UITableViewCell protocol.
My application is rather basic, it has an usual UIViewController class
class ADScreen: UIViewController{
#IBOutlet var tableView: UITableView!
override func viewDidLoad(){
super.viewDidLoad()
self.tableView.dataSource = self
self.tableView.delegate = self
}
}
with an extension
extension ADScreen: UITableViewDelegate, UITableViewDataSource{
(...)
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch indexPath.row {
case 0:
let cell = tableView.dequeueReusableCell(withIdentifier: "tag")!
return cell
(...)
}
As you can see, I am populating the table with custom cells.
class TTViewCell: UITableViewCell{
#IBOutlet var pickerView: UIPickerView!
(...)
}
extension TTViewCell: UIPickerViewDelegate, UIPickerViewDataSource{
(...)
}
The problem is that the class of the cell also has a UIPickerView outlet that I would like to populate, but can't because I have no initialiser to put the pickerView.delegate = self line in, and I'm not sure where do I put it in this case. I've tried to create a custom init() function but it got really complicated over time and wouldn't work anyway with my implementation.
Use override method awakeFromNib() to initialize any properties.
class TTViewCell: UITableViewCell{
#IBOutlet var pickerView: UIPickerView!
override func awakeFromNib() {
super.awakeFromNib()
pickerView.delegate = self
}
}
extension TTViewCell: UIPickerViewDelegate, UIPickerViewDataSource{
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 10 // set number of components
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return 5 // set number of rows
}
}
Check this code.

How to pass data between custom table view cells?

I have two custom table views (not table view controller) with custom
cells. I want to select a second cell from MainViewcontroller
and selected
title and price of cell info pass to the second view as
DetailViewController's first and second index labels.
This is my MainViewController.swift
Edit: Here is the answer
import UIKit
class MainViewController: UIViewController, UITableViewDataSource, UITableViewDelegate,
UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
#IBOutlet weak var searchBar: UISearchBar!
#IBOutlet weak var mainTableView: UITableView!
var imageNames = [ImageNames]()
var searchFoods: [String]!
var priceFood: [Double]!
var searching = false
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tabBarController?.tabBar.isHidden = false
}
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.isHidden = true
let foodCell = Food(name: ["Hamburger big mac",
"Patates",
"Whopper",
"Steakhouse"], price: [15.0, 20.0, 25.0, 30.0])
searchBar.delegate = self
searchFoods = foodCell.name
priceFood = foodCell.price
imageNames = [
ImageNames(name: "images"),
ImageNames(name: "unnamed"),
ImageNames(name: "unnamed")
]
}
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return section == 0 ? 1 : searchFoods.count
// return section == 0 ? 1 : foodNames.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return indexPath.section == 0 ? 130 : 65
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return indexPath.section == 0 ? 100 : 65
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "MainFoodTableViewCell", for: indexPath) as! MainFoodTableViewCell
cell.mainFoodCollectionView.delegate = self
cell.mainFoodCollectionView.dataSource = self
cell.mainFoodCollectionView.reloadData()
cell.mainFoodCollectionView.tag = indexPath.row
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "CellForFood", for: indexPath) as! MainFoodTitleTableViewCell
cell.titleLabel?.text = searchFoods[indexPath.row]
cell.priceLabel?.text = priceFood[indexPath.row].description
return cell
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "cellForFoodSegue" {
if let destinationViewController = segue.destination as? DetailViewController
{
let indexPath = self.mainTableView.indexPathForSelectedRow!
var foodNameArray: [String]
var foodPriceArray: [Double]
foodNameArray = [searchFoods[indexPath.row]]
foodPriceArray = [priceFood[indexPath.row]]
destinationViewController.detailFoodName = foodNameArray
destinationViewController.detailFoodPrice = foodPriceArray
}
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imageNames.count
}
//MARK:- collection view cell size
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = UIScreen.main.bounds.width
return CGSize(width: width, height: 130)
}
//MARK:- //collection view cell data
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MainFoodCollectionViewCell", for: indexPath) as! MainFoodCollectionViewCell
let img = imageNames[indexPath.row]
cell.mainFoodImage.image = UIImage(named: img.name)
return cell
}
}
//MARK:- SearchBar data
extension MainViewController : UISearchBarDelegate {
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
self.searchBar.showsCancelButton = true
mainTableView.reloadData()
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
mainTableView.reloadData()
searchBar.showsCancelButton = false
searchBar.text = ""
searchBar.resignFirstResponder()
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
searchFoods = searchText.isEmpty ? searchFoods : searchFoods.filter { (item: String) -> Bool in
return item.range(of: searchText, options: .caseInsensitive, range: nil, locale: nil) != nil
}
mainTableView.reloadData()
}
}
Edit: Here is my DetailViewController
import UIKit
class DetailViewController: UIViewController {
#IBOutlet weak var foodTitle: UILabel!
#IBOutlet weak var foodSubTitle: UILabel!
#IBOutlet weak var foodPiece: UILabel!
#IBOutlet weak var foodPrice: UILabel!
#IBOutlet weak var drinkPicker: UITextField!
#IBOutlet weak var menuPieceStepper: UIStepper!
var drinkPickerView = UIPickerView()
var selectDrinkType: [String] = []
var detailFoodName : [String] = []
var detailFoodPrice : [Double] = [0.0]
let foods = Food(name: ["Hamburger big mac",
"Patates",
"Whopper",
"Steakhouse"], price: [15.0, 20.0, 25.0, 30.0])
#IBAction func foodPieceStepper(_ sender: Any) {
}
#objc func foodPieceChangeStepper() {
let res = menuPieceStepper.value + foods.price.first!
foodPrice.text = "\(res)"
}
#IBAction func addBasket(_ sender: Any) {
let destinationVC = MyCartViewController()
destinationVC.fromDetailFoodNames = foods.name
destinationVC.fromDetailFoodPrices = foods.price
dismiss(animated: true)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if(segue.identifier == "addToCartSegue") {
if let addToCartVC = segue.destination as? MyCartViewController {
addToCartVC.fromDetailFoodNames = [foodTitle.text]
addToCartVC.fromDetailFoodPrices = foods.price
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
menuPieceStepper.value = 0.0
menuPieceStepper.minimumValue = 0.0
menuPieceStepper.maximumValue = 30.0
menuPieceStepper.stepValue = foods.price.first!
menuPieceStepper.addTarget(self, action: #selector(foodPieceChangeStepper), for: .valueChanged)
drinkPickerView.delegate = self
drinkPicker.inputView = drinkPickerView
selectDrinkType = ["Ayran", "Kola", "Su", "Fanta", "Şalgam", "Sprite"]
foodTitle.text = detailFoodName.description
foodPrice.text = detailFoodPrice.description
self.navigationController?.navigationItem.title = "Sipariş Detayı"
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.dismissKeyboard (_:)))
self.view.addGestureRecognizer(tapGesture)
}
#objc func dismissKeyboard (_ sender: UITapGestureRecognizer) {
drinkPicker.resignFirstResponder()
}
override func viewWillAppear(_ animated: Bool) {
self.navigationController?.navigationBar.isHidden = false
}
override func viewWillDisappear(_ animated: Bool) {
self.navigationController?.navigationBar.isHidden = true
}
}
extension DetailViewController: UIPickerViewDelegate, UIPickerViewDataSource {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return selectDrinkType.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return selectDrinkType[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
let selectedDrink = selectDrinkType[row]
drinkPicker.text = selectedDrink
}
}
Aren't you looking for prepare(for segue: sender:) method? Usually you need to bind a cell prototype to a detail view with a segue, and when the cell is selected the segue is followed just after that method is called to prepare data injection to the detail view.

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()
}

Resources