In my main page, I created a xib file for UITableViewCell. I'm loading the cell from that xib file and its working fine.
Inside of the cell I have some labels and buttons. I'm aiming to change the label by clicking to the button on the cell.
My Code likes below
import UIKit
class SepetCell: UITableViewCell{
@IBOutlet var barcode: UILabel!
@IBOutlet var name: UILabel!
@IBOutlet var fav: UIButton!
@IBOutlet var strep: UIStepper!
@IBOutlet var times: UILabel!
@IBAction func favoriteClicked(sender: UIButton) {
println(sender.tag)
println(times.text)
SepetViewController().favorite(sender.tag)
}
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
}
}
This is my xib files behind codes as .swift.
The codes in the main page likes below:
import UIKit
import CoreData
class SepetViewController: UIViewController, UITextFieldDelegate, UITableViewDataSource, UITableViewDelegate {
@
IBOutlet
var sepetTable: UITableView!
var barcodes: [CART] = []
let managedObjectContext = (UIApplication.sharedApplication().delegate as!AppDelegate).managedObjectContext
override func viewWillAppear(animated: Bool) {
if let moc = self.managedObjectContext {
var nib = UINib(nibName: "SepetTableCell", bundle: nil)
self.sepetTable.registerNib(nib, forCellReuseIdentifier: "productCell")
}
fetchLog()
sepetTable.reloadData()
}
func fetchLog() {
if let moc = self.managedObjectContext {
barcodes = CART.getElements(moc);
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) - > Int {
return self.barcodes.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) - > UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("productCell") as ? SepetCell
if cell == nil {
println("cell nil")
}
let product: CART
product = barcodes[indexPath.row]
cell!.barcode ? .text = product.barcode
cell!.name ? .text = product.name
cell!.fav.tag = indexPath.row
return cell!
}
func favorite(tag: Int) {
}
}
When i clicked fav button inside of the Cell. I wanted to change times label text to anything for example.
When I clicked to the fav button, the event will gone to the SepetCell.swift favoriteClicked(sender: UIButton) function.
So if i try to call: SepetViewController().favorite(sender.tag)
It will go inside of the
func favorite(tag: Int) {
sepetTable.reloadData()
}
but sepetTable is nil when it is gone there. I think it is because of when I call this SepetViewController().favorite(sender.tag) function. It firstly creates SepetViewController class. So because of object is not setted it is getting null.
How can I reach that sepetTable or what is the best way to solve this issue.
Thanks.
Then we should create a swift button action process method ( func onClick(sender: UIButton!) ) to handle the button on-click event. Call the UIButton object's addTarget method to connect the button with the onClick event. This line of code should be placed inside the above viewDidLoad method.
add an 'indexPath` property to the custom table cell. initialize it in cellForRowAtIndexPath. move the tap handler from the view controller to the cell implementation. use the delegation pattern to notify the view controller about the tap event, passing the index path.
Popular patterns for solving this problem are closures and delegates. If you want to use closures, you would do something like this:
final class MyCell: UITableViewCell { var actionBlock: (() -> Void)? = nil
then
@IBAction func didTapButton(sender: UIButton) { actionBlock?() }
then in your tableview delegate:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) - > UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("MyCellIdentifier") as? MyCell cell?.actionBlock = { //Do whatever you want to do when the button is tapped here }
A popular alternative is to use the delegate pattern:
protocol MyCellDelegate: class { func didTapButtonInCell(_ cell: MyCell) } final class MyCell: UITableViewCell { weak var delegate: MyCellDelegate?
then
@IBAction func didTapButton(sender: UIButton) { delegate?.didTapButtonInCell(self) }
.. Now in your view controller:
then in your tableview delegate:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) - > UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("MyCellIdentifier") as? MyCell cell?.delegate = self
And add conformance to the protocol like this:
extension MyViewController: MyCellDelegate { didTapButtonInCell(_ cell: MyCell) { //Do whatever you want to do when the button is tapped here } }
Hope this helps!
All patterns above are fine. my two cents, in case You add by code (for example multiple different cells and so on..) there is a FAR simple solution.
As buttons allow to specify a "target" You can pass directly the controller AND action to cell/button when setting it.
In controller:
let selector = #selector(self.myBtnAction)
setupCellWith(target: self, selector: selector)
...
in custom cell with button:
final func setupCellWith(target: Any? selector: Selector){
btn.addTarget(target,
action: selector,
for: .touchUpInside)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With