For some reason, the delegate method is not being called. I am printing the delegate property in the console but it returns nil. I was looking for other answers here, but none of them were helpful for me.
protocol FilterSwitchDelegate {
func switchValueChanged(tagValue:Int)
}
class FilterTableViewCell: UITableViewCell {
#IBOutlet weak var filterLabel: UILabel!
#IBOutlet weak var filterSwitch: UISwitch!
var delegate:FilterSwitchDelegate?
#IBAction func filterSwitchValueChanged(_ sender: UISwitch) {
print(sender.tag)
delegate?.switchValueChanged(tagValue: sender.tag)
}
}
//In FilterViewController I am calling this delegate method
class FilterViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var dataSource = FilterTableViewCell()
var filterModel = [FilterVCDataModel]()
var ids = [Int]()
override func viewDidLoad() {
super.viewDidLoad()
dataSource.delegate = self
}
}
extension FilterViewController: FilterSwitchDelegate {
func switchValueChanged(tagValue: Int) {
ids.remove(at: tagValue)
print(ids)
}
}
TableView dataSource and delegate methods
extension FilterViewController:UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filterModel.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "filterCell", for: indexPath) as! FilterTableViewCell
cell.filterSwitch.tag = indexPath.row
cell.filterLabel.text = filterModel[indexPath.row].filterData["title"] as? String
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 66
}
}
in the cellForRow you have to dequeue your cell.
let cell = tableView.dequeueReusableCell(withIdentifier: "yourId") as? FilterTableViewCell
cell.delegate = self
return cell
and the job is done
Related
I have two custom TableViewCells. So first TableViewCell is like a recent list, it can become longer. but second cell is always stays at bottom. so i need to add UILabel that hold's secondTableViewCell. the result that i need.
import UIKit
class bagPage: UIViewController, UITableViewDelegate, UITableViewDataSource {
var itemsName: [String] = []
var itemsPhoto: [UIImage] = []
// these arrays will defined in other view controller
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.row < itemsName.count{
return 165
}else{
return 50
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 6 + itemsName.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row < itemsName.count{
let cell = tableView.dequeueReusableCell(withIdentifier: "bagTableViewCell") as? bagTableViewCell
cell?.itemName.text = itemsName.last
cell?.itemPhoto.image = itemsPhoto.last
return cell!
}
if indexPath.row == itemsName.count {
let cellTwo = tableView.dequeueReusableCell(withIdentifier: "extraBagPageTableView") as? extraBagPageTableView
// here i'm hiding views in first row
cellTwo?.textLabel?.text = "These are products that u can add to your cell"
return cellTwo!
}else{
let cellTwo = tableView.dequeueReusableCell(withIdentifier: "extraBagPageTableView") as? extraBagPageTableView
return cellTwo!
}
}
}
This is another attempt at providing a solution. Is this what you are looking for?
Here is a link to the project
https://drive.google.com/file/d/1XlSF4fGiNzOqQHauiNo7TuFhKUTrFbsJ/view?usp=sharing
Let me know if you need more help
Good evening, so I followed your image and made the code follow your convention of 1 tableview section, 2 difference cells. I tried to use your naming convention. Note I had to swap around the height values, you had them wrong way round.
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var itemsName: [String] = ["Helmet", "Gloves", "Bindings", "Goggles", "Kneepads", "Boots", "Snowboard"]
override func viewDidLoad() {
super.viewDidLoad()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1 + itemsName.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row < itemsName.count{
let bagTableViewCell = tableView.dequeueReusableCell(withIdentifier: "BagTableViewCell") as? BagTableViewCell
bagTableViewCell?.productsLabel.text = itemsName[indexPath.row]
return bagTableViewCell!
} else {
let extraBagPageTableView = tableView.dequeueReusableCell(withIdentifier: "ExtraBagPageTableView") as? ExtraBagPageTableView
return extraBagPageTableView!
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.row < itemsName.count {
return 50
} else {
return 165
}
}
}
And the tableview cells. Please note the second cell has a bad name.
class BagTableViewCell: UITableViewCell {
#IBOutlet weak var additionalProductsLabel: UILabel!
#IBOutlet weak var productsLabel: UILabel!
#IBOutlet weak var productImage: UIImageView!
}
class ExtraBagPageTableView: UITableViewCell {
}
And altogether it looks like this
And the project can be found here. (I set the permissions correctly this time :) )
TableCellWithLabel Project
I currently have a TableView which is sitting inside a prototype TableViewCell. To remove confusion the hierarchy is as follows:
TableViewController
--> TableViewCell
--> TableView
I am trying to access the indexPath.section in which the TableView is located, as for each different cell inside the TableViewController, I want to display different data in the TableView.
My code currently as follows:
class TableViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "todayCell", for: indexPath) as! MyTableViewCell
// Configure the cell...
switch indexPath.section {
case 0:
cell.label.text = "Today"
case 1:
cell.label.text = "Tomorrow"
default:
cell.label.text = "Error"
}
return cell
}
}
For my TableViewCell:
class MyTableViewCell: UITableViewCell, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var label: UILabel!
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var cancelButton: UIButton!
#IBOutlet weak var completeButton: UIButton!
var numOfRowsOne = 6
var numOfRowsTwo = 7
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var rows = 0
if (TableViewController Cell's indexPath.section) == 0 {
rows = numOfRowsOne
} else {
rows = numOfRowsTwo
}
return rows
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = todayTableView.dequeueReusableCell(withIdentifier: "activitiesCell", for: indexPath)
return cell
}
}
Thank you!
You can get indexPath as below,
if let ip = (self.superview as? UITableView)?.indexPath(for: self), ip.section == 0 {
rows = numOfRowsOne
} else {
rows = numOfRowsTwo
}
I want to take selected cell as a text, and save it in "var productName" as a String. I've tried to use didSelectRowAt funcion, but I don't know how to implement it.
That's my code:
import UIKit
class ChooseProductViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var productName: String? = ""
var workModel: ActualValues?
var closureBlock2: (() -> Void)?
#IBOutlet weak var checkButton: UIButton!
let productList : [String] = ["Almond 20g",
"Almond 40g",
"Baharat Spice Mix 2g",
"Baharat Spice Mix 4g",
]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return productList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let myCell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
myCell.textLabel?.text = productList[indexPath.row]
return myCell
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func checkButton(_ sender: UIButton) {
workModel?.product = productName
closureBlock2?()
self.dismiss(animated: true, completion: nil)
}
func configureProduct(model: ActualValues) {
workModel = model
}
}
How can I fix it?
Something like this is probably what you want?
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
productName = productList[indexPath.row]
}
And make sure you've set the data source and delegate, and that the table view allows seletion:
override func viewDidLoad() {
super.viewDidLoad()
tableView.allowsSelection = true
tableView.dataSource = self
tableView.delegate = self
}
I have created a tableView with two different labels and one textfield. Depending on the indexPath in which is selected the labels will display different text according to the array. I have created a CocoTouch Class file and made it type TableViewCell.
TableViewCell.swift
import UIKit
class Driver_Navigation_TableViewCell: UITableViewCell {
#IBOutlet weak var orderTextField: UITextField!
#IBOutlet weak var adressLabel: UILabel!
#IBOutlet weak var nameLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
ViewController.swift
class ViewController: UIViewController, MGLMapViewDelegate, UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate {
var allCellsText = [String]()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
array.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! Driver_Navigation_TableViewCell
cell.adressLabel.text = passengersAdress[indexPath.row]
cell.nameLabel.text = passengersName[indexPath.row]
cell.orderTextField.placeholder = "\(indexPath.row + 1)."
return(cell)
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath as IndexPath) as! Driver_Navigation_TableViewCell
cell.orderTextField.tag = indexPath.row
cell.orderTextField.delegate = self // theField is your IBOutlet UITextfield in your custom cell
return cell
}
func textFieldDidEndEditing(textField: UITextField) {
allCellsText.append(textField.text!)
print(allCellsText)
}
}
You cant have duplicate UITableViewDataSource and UITableViewDelegate methods it won't work like that.
Also in your code you have not set the delegate for the textField in both the cellForRowAtIndexPath() methods.
If you want to have two table view in a single controller try the following
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
func tableView(_ tableView: UITableView, cellForRowAtIndexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! Driver_Navigation_TableViewCell
if tableView == self.tableView1 {
cell.adressLabel.text = passengersAdress[indexPath.row]
cell.nameLabel.text = passengersName[indexPath.row]
cell.orderTextField.placeholder = "\(indexPath.row + 1)."
}
else {
cell.orderTextField.tag = indexPath.row
}
cell.orderTextField.delegate = self
return(cell)
}
Create outlets for the Table View
I am using two view Controllers i.e. StateListVC and PlayVC. In StateListVC, I am using container view with 3 VCs. After tapping on 3rd View Controller, I am going to PlayVC with delegate method. I don't know how to do that. Please help me to resolve this issue.
StateListVC
class StateListVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
if isMoveToAnotherVC
{
let vc = self.storyboard?.instantiateViewController(withIdentifier: "PlaceVC") as! PlaceVC
vc.delegate = self
}
}
}
extension StateListVC: MoveToAnotherVC {
func moving(string: String) {
print(string)
}
}
ThirdVC
protocol MoveToAnotherVC {
func moving(string: String)
}
class PlaceVC: UIViewController {
#IBOutlet weak var tableViewPlace: UITableView!
var delegate: MoveToAnotherVC? = nil
var arrPlace = ["Place1", "Place2"]
override func viewDidLoad() {
super.viewDidLoad()
}
extension PlaceVC: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrPlace.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = arrPlace[indexPath.row]
return cell
}
}
extension PlaceVC: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
isMoveToAnotherVC = true
print(delegate)
guard let delegate = self.delegate else{
print("Delegate not set")
return
}
delegate.moving(string: "test")
}
}
This is hooked up fine:
protocol MoveToAnotherVC: AnyObject {
func moving(string: String)
}
class StateListVC: UIViewController, MoveToAnotherVC {
override func viewDidLoad() {
super.viewDidLoad()
let vc = self.storyboard?.instantiateViewController(withIdentifier: "PlaceVC") as! PlaceVC
vc.delegate = self
}
func moving(string: String) {
print(string)
}
}
class PlaceVC: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableViewPlace: UITableView!
weak var delegate: MoveToAnotherVC?
var arrPlace = ["Place1", "Place2"]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrPlace.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = arrPlace[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
delegate?.moving(string: "test")
}
}
I made the protocol a class protocol, moved the view controller instantiation into viewDidLoad, removed some (what I consider) extraneous unwrapping, and stripped your protocol/delegate pattern down to the basics. This works. I would plug this into your project and add what you need piece by piece until it breaks because your problem is outside of this. I suspect it may have to do with something you didn't include in your question but this answers your question about how to set up a protocol/delegate pattern.