Get Class from UITableViewCell identifier - ios

I have a big bunch of subclasses of UITableViewCell, all of these cells have a class method that returns the estimated height for the type of cell...
So what I want to do is be able to call that method just by knowing the cell identifier (I don't want to use a Switch mapping identifier with Class). I can't think of a way of doing it...
I know there is a NSClassFromString but I can't use that because my objects don't inherit from NSObject...
Any idea?

You could assign the class name as the cell identifier and then do this:
Class cellClass = NSClassFromString(cellIdentifier);

You can get the cell in cellForRowAtIndexPath by calling dequeueReusableCellWithIdentifier and cast it to your custom cell type. Then you can call any method you want.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCellWithReuseIdentifier(myIdentifier, forIndexPath: indexPath) as! MyTableViewCell
// call class methods here
return cell
}
}

Related

Set TextLabel's text in tableViewCell

I am coming to you for a little issue I have, that might actually not be that complicated but that i have struggled about for now about an hour...
I defined a TableViewCell in a TableViewController. This TableViewCell has three UIImage and two textLabels. I implemented the following methods :
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return fruits.count
}
(which in my sense defines the number of rows)
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "friendListCell")
cellOutlet.nameTextLabel.text = fruits[indexPath.row]
return cell!
}
On this second method, the "cellOutlet" is an instance of the class that defines my cell, in which I modify one of the textLabel's text.
"fruits" is a simple array of Strings that are supposed to be displayed in every cell of my app one by one.
Compilation goes fine, but when accessing the page in question, the app crashes saying
unexpectedly found nil while unwrapping an Optional value
My question is the following :
Would you have any idea of what is done wrong in term of accessing my textLabel's text ?
Thanks in advance !
If you're using a custom TableViewCell class you have to
Set the class of the cell in Interface Builder to the custom class
Cast the cell accordingly in cellForRow... (assuming the name is MyTableViewCell)
let cell = tableView.dequeueReusableCell(withIdentifier: "friendListCell" for:indexPath) as! MyTableViewCell
Try to call
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "friendListCell")
cell.nameTextLabel.text = fruits[indexPath.row]
return cell!
}
and also check "cell" should not be nil at the time of calling cell.nameTextLabel.text = fruits[indexPath.row]
Even if your custom UITableViewCell class (e.g. FruitsCell) has some labels, the standard UITableViewCell doesn't (apart from one, which is its 'label' property). In your code, the 'cell' property is of type UITableViewCell, which has no cellOutlet or nameTextLabel property to access.
If you set up your custom cell in IB, be sure to connect all your labels from IB with the code in your Swift-File, e.g. FruitsCell.swift, that contains the FruitsCell class.
Then cast the 'cell' in your ViewControllers delegate method as e.g. FruitCell instead of UITableViewCell. Only then you can access the labels of that class that you set up in IB.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// casting to your Class
let cell = tableView.dequeueReusableCell(withIdentifier: "friendListCell") as! FruitCell
// accessing that Class' properties
cell.nameTextLabel.text = fruits[indexPath.row]
// returning cell of type FruitCell
return cell!
}

New or Existing cell when using dequeueReusableCellWithIdentifier:forIndexPath:?

Having a UITableViewControllerand using:
override func tableView(tableView: UITableView, cellForRowAtIndexPath
indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath) as! UITableViewCell
return cell
}
Using dequeueReusableCellWithIdentifier:forIndexPath:'' instead ofdequeueReusableCellWithIdentifier`` how can I determine if a cell is a new one or a reused one?
Create your own custom cell class to use for the reuse identifier. Then, inside that cell, implement awakeFromNib and make your changes to the cell. This will only be called once when your cell is loaded from its NIB file.
Any other changes that need to be made when the cell is reused can be made in prepareForReuse.

Retrieve object from custom UITableViewCell on selection

So I have a UITableView populated with custom UITableViewCell. Every cell is loaded with an object i would like to retrieve upon row selection.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// Here I would like to retrieve the object associated with the selected row.
// Object "cell" is inferred as a UITableViewCell, not as CustomTableViewCell :(
var cell = myTableView.cellForRowAtIndexPath(indexPath)
}
As described above, I can't access the CustomTableViewCell in order to get the associated object. Is there another way of doing this?
Usually, your UITableView is backed up by a data source, which is e.g. an array. Therefore, use the provided indexPath to get the object from the array.
Apart from that, you can also cast the cell to your custom class:
var cell = myTableView.cellForRowAtIndexPath(indexPath) as CustomTableViewCell
You should cast it to CustomTableViewCell, try that:
var cell = myTableView.cellForRowAtIndexPath(indexPath) as CustomTableViewCell
You have to type cast to the class which you have used when constructing the cell.
let cell = myTableView.cellForRowAtIndexPath(indexPath) as UITableViewCell
or
let cell = myTableView.cellForRowAtIndexPath(indexPath) as MyTableViewCellClass

Passing parameters to custom UITableViewCell [duplicate]

This question already has answers here:
How to reference UITableViewController from a UITableViewCell class?
(6 answers)
Closed 8 years ago.
I'm registering a custom cell from a Nib in the TableViewController
tableView.registerNib(UINib(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: "Cell")
but my CustomCell has IBAction methods that need access to the tableView itself and the fetchedResultsController. How do I pass those parameters in a clean way to the CustomCell?
Setting those things in:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) {
return tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
}
doesn't seem to be the clean way to me..?
The cell really shouldn't know anything about the table view or the fetchedResultsController. One way to do this is to add your actions in cellForRowAtIndexPath, and make the controller the target.
Another option is to have the action methods in the custom cell class, and have them call delegate protocol methods that you create in the cell class. Have the controller set itself as the delegate in cellForRowAtIndexPath.
You can select the class that is responsible for Custom Cell IBAction example
IBAction Func enterKeyButton (sender: AnyObject) {
println(sender)
}
and in tableview implement the method and that's the way of the cause medot Custom Cell
func tableView (tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.dequeueReusableCellWithIdentifier ("Cell", forIndexPath: indexPath) as UITableViewCell
cell.enterKeyButton ("hello")
return cell
}
I hope I helped you!

Swift TableViewController reuseIdentifier never works

I'm working in Swift with one TableViewController with one prototype cell. The cell has a reuse identifier specified in the storyboard, but it never dequeues properly. I always get the "unexpectedly found nil while unwrapping an Optional value" error.
I've properly registered the class as follows:
self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "myNewCell")
The offending code is:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("myNewCell") as UITableViewCell
let textField = cell.viewWithTag(123) as UITextField
textField.text = "test"
return cell
}
I feel like I've tried everything here but it never properly gives a cell with that identifier. Even using the fallback (if nil, create a cell with that identifier) still gives the error. It's definitely having trouble getting a cell with that identifier, but it's registered and specified in the storyboard... Any assistance is greatly appreciated!
When using cell prototypes, you do not call registerClass. The storyboard does that for you. If the cell prototype has its identifier specified, then just all dequeueReusableCellWithIdentifier and it should find your cell prototype without incident.
I'd suggest checking the spelling/capitalization of the identifier in storyboard and make sure it is identical to what is used in cellForRowAtIndexPath code.
I notice that you are trying to access a cell's label using a tag number. Nowadays, when dealing with custom cell layouts, we'd generally create our own table view subclass, e.g.:
// CustomTableViewCell.swift
import UIKit
class CustomTableViewCell: UITableViewCell {
#IBOutlet weak var customTextField: UITextField! // note, I would use something other than textLabel to avoid confusion with base class
}
We'd then go to our cell prototype and specify its base class:
We'd also set the cell prototype's identifier:
We'd then hook up the outlet between the cell prototype and our custom class #IBOutlet.
Having done all of that, the cellForRowAtIndexPath would be:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("myNewCell", forIndexPath: indexPath) as CustomTableViewCell
cell.customTextField.text = "Row \(indexPath.row)"
return cell
}
If dequeueReusableCellWithIdentifier is giving you problems then just don't use it.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = UITableViewCell()
let textField = cell.viewWithTag(123) as UITextField
textField.text = "test"
return cell
}

Resources