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
Related
I have a UITableView with a transparent background color and cells which also have a transparent background color. When I reload my tableView with:
dataSource = some new data
tableView.reloadData()
I can see the new cells overlap the old ones.
I did try to use use
tableView.beginUpdates()
// remove all rows here
change data source
// insert new rows here
tableView.endUpdates()
but it did not work. I tried as well tableView.reloadRowsAtIndexPath(...) but still no luck.
And finally I set all my cells and my table view to clear graphic context when redrawn but it did not manage to fix this issue.
Any help would be greatly appreciated.
My cell creation function:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("suggestioncell")
cell.backgroundColor = UIColor.whiteColor().alpha(0.1)
cell.textLabel?.text = (suggestions![indexPath.row] as! SVPlacemark).formattedAddress
cell.clearsContextBeforeDrawing = true
cell.contentView.clearsContextBeforeDrawing = true
return cell
}
Try overriding prepareForReuse in you UITableViewCell subclass, and reset content there.
Here's what the documentation says about that:
Prepares a reusable cell for reuse by the table view's delegate.
If a UITableViewCell object is reusable—that is, it has a reuse identifier—this method is invoked just before the object is returned from the UITableView method dequeueReusableCellWithIdentifier:. For performance reasons, you should only reset attributes of the cell that are not related to content, for example, alpha, editing, and selection state. The table view's delegate in tableView:cellForRowAtIndexPath: should always reset all content when reusing a cell. If the cell object does not have an associated reuse identifier, this method is not called. If you override this method, you must be sure to invoke the superclass implementation.
Custom UITableViewCell class:
class customCell: UITableViewCell {
override func prepareForReuse() {
self.textLabel?.text = nil
}
}
In your cellForRowAtIndexPath method:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("suggestionCell", forIndexPath: indexPath) as! customCell
cell.backgroundColor = UIColor.whiteColor().alpha(0.1)
cell.textLabel?.text = (suggestions![indexPath.row] as! SVPlacemark).formattedAddress
return cell
}
And, of course in your XIB/Storyboard, set the cell class to CustomCell, and set its reuse identifier.
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
}
}
I have a UITableView with prototype cells that essentially takes up the whole page. I have a UIButton on the very bottom that should display a pop-up static UITableView when tapped. I'm struggling to account for the pop-up table view in cellForRowAtIndexPath.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let result: UITableViewCell
if tableView == self.tableView {
var cell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel!.text = array[indexPath.row]
result = cell
} else if tableView == self.popUpTableView {
var popUpCell = self.popUpTableView.dequeueReusableCellWithIdentifier("popUpCell", forIndexPath: indexPath) as! UITableViewCell
popUpCell.textLabel!.text = popUpArray[indexPath.row]
result = popUpCell
}
return result
}
I'm getting an error at return result, where Variable 'result' used before being initialized, but I'm declaring it at the very top. Where am I going wrong with this?
You need to have exhaustive choices. It's possible that result never gets initialized because your checks are "if" and "else if". What happens if tableView is not either "self.tableView" or "self.popUpTableView"?
The simple fix is (if you only plan on having these two) to simply change your "else if" to a simple "else". This way result will always get initialized.
I created a Cocoa file with a subclass of UITableViewCell so I could have an outlet to a prototype cell. Would this work?
Create an array with the titles for all your labels. For instance:
var titleLabels: [String] = ["Eggs", "Cheese", "Milk"]
Load your custom cell class (put this in viewDidLoad):
var nib = UINib(nibName: "YourCellSubclass", bundle: nil)
tableView.registerNib(nib, forCellReuseIdentifier: "cell")
Then implement cellForRowAtIndexPath:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell
cell.detailLabel?.text = self.titleLabels[indexPath.row]
return cell
}
(Make sure you remember to set this class as the datasource for your tableview).
To include the quantities on the cells, you'll need another array of numbers (or better yet, an array of objects, each with a name and quantity attribute). Then (assuming your cell has two labels - one for the title, one for the quantity) you can set both the titleLabel and quantityLabel on your cell in the same manner as shown above.
This article has a pretty good walkthrough on creating custom tableview cells: https://www.weheartswift.com/swifting-around/
You could create the custom UITableViewCell with two UILabels, for example titleLabel and detailLabel. In the custom initWithStyle method, you can set the desired position of the labels within the cell.
After initializing the custom cell, you could write another method in the custom UITableViewCell class that sets the text values of titleLabel and detailLabel, and call that method from cellForRowAtIndexPath. The desired values could come from an NSArray, and you would use the cell row, indexPath.row, to fetch the corresponding values from the array.
I am trying to get a custom tableView cell with a textView inside working in my tableView. I have made a custom UITableViewCell with a textView inside it.
I can get the custom made UITableViewCell with the textView inside to appear in the UITableView.
I can click inside the textView to type something, but when I finish typing and click on another tableViewCell, the first tableViewCell with the textView inside disappears. After disappearing, it becomes an empty tableViewCell. XCode gives this message:
"no index path for table cell being reused"
However, when I scroll away in the tableView and scroll back to the empty tableViewCell, it reappears.
I don't know how to keep the tableViewCell from disappearing. It seems like the answer has something to do with using the restorationIdentifier inside of UITableView, but I'm not sure how to use it. In the docs, it says to use restorationIdentifier for state preservation.
Here is the relevant code I have:
inside ViewDidLoad():
tableView.registerClass(PhotoAndRateTableViewCell.classForCoder(), forCellReuseIdentifier: ReuseIds.reviewCell)
tableView.registerNib(UINib(nibName: "PhotoAndRateTableViewCell", bundle: NSBundle.mainBundle()), forCellReuseIdentifier: ReuseIds.reviewCell)
inside cellForRowAtIndexPath:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var section = indexPath.section
let cell = UITableViewCell()
var cell = tableView.dequeueReusableCellWithIdentifier(ReuseIds.reviewCell, forIndexPath: indexPath) as PhotoAndRateTableViewCell
cell.selectionStyle = UITableViewCellSelectionStyle.None
return cell
}
You're misusing the dequeue procedure:
var cell = tableView.dequeueReusableCellWithIdentifier(ReuseIds.reviewCell, forIndexPath: indexPath) as? PhotoAndRateTableViewCell
if (cell == nil) {
cell = PhotoAndRateTableviewCell();
}
You want to reuse a cell if available, or create a new one if not. In your case, you're creating a cell every time (of the generic class) and then attempting to dequeue a cell from your custom class (which has never been created)
As far as preserving the data, you need to implement the prepareForReuse method in the table cell which should clear whatever index specific data was contained in the cell. Then in cellForRow you can re-set the data for the cell for re-appearance