Ambiguous reference to member 'tableView' when dequeuing a cell - ios

I'm running into an odd error. This line of code functions correctly:
let cell = self.tableView.dequeueReusableCellWithIdentifier("FeedCell", forIndexPath: indexPath) as UITableViewCell!
However when I cast to FeedCell! (a subclass of UITableViewCell):
let cell = self.tableView.dequeueReusableCellWithIdentifier("FeedCell", forIndexPath: indexPath) as FeedCell!
Xcode throws the error: Ambiguous reference to member 'tableView'
I'm not sure how it can be ambiguous, let alone triggered by a different casting!

Try changing the line to
let cell = tableView.dequeueReusableCellWithIdentifier("FeedCell", forIndexPath: indexPath) as! FeedCell
Just remove the ! from FeedCell! and put it in as! and check if there is any difference.
Beside as #redent84 mentioned in his comment you should use tableView instead of self.tableView.

Related

Force downcast when programming a custom UITableViewCell in Swift

In the following code:
let cell = tableView.dequeueReusableCell(
withIdentifier: "MyCell",
for: indexPath
) as MyTableViewCell // 'UITableViewCell' is not convertible to 'MyTableViewCell'; did you mean to use 'as!' to force downcast?
We have the error complaining that UITableViewCell is not convertible to a MyTableViewCell.
So the compiler suggests to do a force cast:
let cell = tableView.dequeueReusableCell(
withIdentifier: "MyCell",
for: indexPath
) as! MyTableViewCell // ?!?!?!
However, that feels ugly.
Is there no alternative to force casting when dealing with tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)? Is this really the most idiomatic way to accomplish this in Swift?
Thanks!
Is this really the most idiomatic way
Absolutely. It's perfectly standard.
You could downcast safely like this:
if let cell = tableView.dequeueReusableCell(
withIdentifier: "MyCell",
for: indexPath
) as? MyTableViewCell {
But this is one situation where I don't think that's worth doing, because if this turns out not to be a MyTableViewCell, there's a very real sense in which you want to crash.
You can do it like this:
guard let cell = tableView.dequeueReusableCell(
withIdentifier: "MyCell",
for: indexPath
) as? MyTableViewCell else {
// Log an error, or fatalError("Wrong cell type."), etc.
// or maybe return UITableViewCell()
}

Swift 3 Generic cannot convert value of type UITableViewCell

I have a custom cell that can accept a generic type.
class MyCell<T>: UITableViewCell where T: MyCellDataSource, T: MyCellDelegate
How do I use it or type cast or infer it when dequeueing a cell?
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
In Swift 3.0
I had recently worked with the same implementation.
I solved this by the following a code.
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? MyCell<TName>
//Configure cell here
return cell!
Hope it helps

Tailor forced casts conflicts

let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! CustomTableViewCell
It's standard sentence that implements the table view's cell's properties. But Tailor (it's a Swift analyzer/linter) warns about you shouldn't forced the CustomTableViewCell as as! If I used to as as?, I have to implement cell's properties as cell!. But Tailor don't warn about [forced-type-cast] Force casts should be avoided. What's the reason of this? How can I implement cell's without unwrap of cell as cell! What's the correct programming paradigms for forced casts operations in Swift?
I am not familiar with "Tailor" but most likely the reason it is giving you this warning is because if a force cast fails then obviously your program will crash and thats never good.
The as! operator does have its place if you are 100% sure that what you are casting is of that type. But, even then its better to be safe than sorry and you should use a guard or if let statement instead in order to handle a failed cast.
if let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as? CustomTableViewCell {
//do what you like with cell
}
or
guard let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as? CustomTableViewCell else {
//abort current scope, return, break, etc. from scope.
}
//do what you like with cast cell

Cannot convert from UITableViewCell to specified type

I am converting an app from objective-c to swift. I did not write the objective c code. One of the functions which code is as below...
func tableView (tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier: String = "Cell"
var cell: ListCell? = tableView.dequeueReusableCellWithIdentifier(cellIdentifier)!
And theres more code in the function but i don't think it is relevant. When I run the app, I get an error: "nil found while unwrapping an optional" at the line where I create the variable cell. The error is occurring because I am trying to convert a UITableViewCell to ListCell type. And the conversion is occurring and returning nil. I need to have this line in the code because it is there in the objective-c version of the app.
Is there any way I can get around this and convert a UITableViewCell to ListCell without the conversion failing and returning nil?
Here is the declaration of the ListCell class...
#interface ListCell : UITableViewCell {
//code
}
I did not convert the ListCell class to swift, and instead use a bridging header. Also ListCell is a subclass of UITableViewCell, so why is the conversion not working.
There are two ways you can use dequeueReusableCellWithIdentifier - The most common "modern" way is to have registered the reuse identifier and specified a custom class for your cell in your storyboard. You can also use the UITableView method registerClass:forCellReuseIdentifier to do the same thing programatically.
tableview.registerClass(ListCell.self, forCellReuseIdentifier:"Cell")
In this case you would say
var cell=tableview.dequeueReusableCellWithIdentifier(cellIdentifier) as! ListCell
You can use a forced downcast because you know that the dequeue operation will return a cell of the appropriate type (and if not then you have a problem and throwing an exception is good so you can debug it).
The "old" way was not to register a class and deal with the fact that dequeueReusableCellWithIdentifier may return nil - In this case you need to allocate a new cell yourself;
var cell:Listcell
if let reuseCell = tableview.dequeueReusableCellWithIdentifier(cellIdentifier) as? ListCell {
cell=reuseCell
} else {
cell=ListCell(style: .Default, reuseIdentifier: cellIdentifier)
}
// Now you can configure cell...
Try this, it should work fine.
func tableView (tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cellIdentifier: String = "Cell"
var cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as! ListCell
You should use this version:
let cell = tableView.dequeueReusableCellWithIdentifier("Cell",
forIndexPath: indexPath) as! ListCell
The dequeue method version with index path never returns nil (creates new cells automatically, when needed).
The force cast as! either succeeds with a non-optional value, or crashes the app (in this case if the cell was not actually ListCell).
it should be
var cell: ListCell? = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as! ListCell

How to get UITableViewCell object from indexPath in Swift?

I'm trying to get UITableViewCell object programmatically using Swift, so I wrote this code:
let cell:UITableViewCell = (UITableViewCell) UITableView.cellForRowAtIndexPath(indexPath.row)
but getting compile error as:
Cannot convert value of type '(UITableViewCell).Type' to specified type 'UITableViewCell'
Consecutive statements on a line must be separated by ';'
Instance member 'cellForRowAtIndexPath' cannot be used on type 'UITableView'; did you mean to use a value of this type instead?
cellForRowAtIndexPath is not a class method. Use the instance method instead.
let cell = tableView.cellForRowAtIndexPath(indexPath)
Swift 3:
let cell = tableView.cellForRow(at: indexPath)
You can use this for Swift 4
let indexPath = IndexPath(row: 0, section: 0)
let cell = tableView.cellForRow(at: indexPath)
First get row number where you want to go then call below code.
let indexPath = IndexPath(row: rowNumber, section: 0)
let tableViewCell = YourTableView.cellForRow(at: indexPath)
Swift 5 Easy solution
//MARK:- Collection View
let cell = yourcollectionview.cellForItem(at: indexPath) as! YourCollectionViewCell
Table View
let cell = tableView.cellForRow(at: indexPath) as! YourTableViewCell
Usage
let tempImage = cell.yourImageView.image!

Resources