Conditional cast from UITableViewCell to UITableViewCell always succeds - ios

When I'm compiling my app, I get a warning and I don't know how to fix or hide it. Conditional cast from UITableViewCell to UITableViewCell always succeeds
This is my part of the code, where the warning appears.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrayPDF.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "MyCellPDF", for: indexPath)
as? UITableViewCell else { return UITableViewCell() }
cell.textLabel?.text = arrayPDF[indexPath.row] + ".pdf"
return cell
}
This part of my code generates the warning.
as? UITableViewCell else { return UITableViewCell() }
Everything is working fine. I'm stuck.
Thanks in advance!

By default, tableView.dequeueReusableCell(withIdentifier: "MyCellPDF", for: indexPath) returns a UITableViewCell object.
So, when you do:
guard let cell = tableView.dequeueReusableCell(withIdentifier: "MyCellPDF", for: indexPath) as? UITableViewCell else { return UITableViewCell() }
You are casting an UITableViewCell object to an UITableViewCell. Xcode just tells you that is useless.
If your class is a UITableViewCell, you can just use:
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCellPDF", for: indexPath)
If it is a custom class, you can use the guard but replace the as? UITableViewCell part with as? MyCustomTableViewCellClass.
Regards,
IMACODE

You used guard .. else{},So it must optional,I guess the function you need is the first not the last:
open func dequeueReusableCell(withIdentifier identifier: String) -> UITableViewCell? // Used by the delegate to acquire an already allocated cell, in lieu of allocating a new one.
#available(iOS 6.0, *)
open func dequeueReusableCell(withIdentifier identifier: String, for indexPath: IndexPath) -> UITableViewCell // newer dequeue method guarantees a cell is returned and resized properly,
You can right with eigther one in this way:
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCellPDF", for: indexPath)
OR
guard let cell = tableView.dequeueReusableCell(withIdentifier: "MyCellPDF") else { return UITableViewCell() }

Related

Understanding Xcode UITableViewCell

I have defined a class named c1 for a prototype cell like follows:
I defined the code for c1 like this:
class c1 : UITableViewCell {
public func configure(indexPath: IndexPath) -> UITableViewCell {
let place = places[indexPath.row]
self.textLabel?.text = place.name
self.detailTextLabel?.text = "\(place.timestamp)"
return self
}
}
Inside the UITableViewController following code:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell1", for: indexPath)
// Configure the cell...
return cell.configure(indexPath);
}
But this works not because obv. the compiler doesn't know about c1: "Value of type 'UITableViewCell' has no member 'configure'"
And I don't understand Why: If I specify the classname "c1" in the storyboard, I expected that XCODE instantiate the appear. class automatically for the reusing mechanism.
So the tableView method should return the runtime instantiated "c1" class which is an child of UITableViewCell to have access to the "configure" method?
just cast the cell to your specific cell
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell1", for: indexPath) as? c1
and the job is done
Must cast the type of UITableview cell
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell1", for: indexPath) as? c1 // to inherit the method of class c1, need to cast
// Configure the cell...
return cell.configure(indexPath);
}
Please ⌥-click on dequeueReusableCell or read the documentation
func dequeueReusableCell(withIdentifier identifier: String, for indexPath: IndexPath) -> UITableViewCell
returns the base class UITableViewCell
If you declare a custom (sub-)class you have to cast the cell to the subclass. By the way please name the class with a starting capital letter.
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell1", for: indexPath) as! c1
And in configure you might have to return Self or c1
public func configure(indexPath: IndexPath) -> Self {
let place = places[indexPath.row]
self.textLabel?.text = place.name
self.detailTextLabel?.text = "\(place.timestamp)"
return self
}
And where does places come from in the cell? The configure method seems to be pointless.
To access the methods of your UITableViewCell you will have to cast the cell to that particular UITableViewCell
i.e
let cell = tableView.dequeueReusableCell(withIdentifier: "YOUR_IDENTIFIER") as? YOUR_CELL_CLASS
In case if you have the multiple UITableViewCell so you have to assign then a different identifier so based on that you can identify the particular cell. More or less there should an awareness which display your cell based on your data.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let aCellType = aCellData[indexPath.row].cellType //aCellData is the predefined data
switch aCellType {
case c1:
let cell = tableView.dequeueReusableCell(withIdentifier: "YOUR_IDENTIFIER") as? YOUR_CELL_CLASS_C1
cell.YOUR_METHOD_OF_THIS_CELL()
return cell
case c2:
let cell = tableView.dequeueReusableCell(withIdentifier: "YOUR_IDENTIFIER") as? YOUR_CELL_CLASS_C2
cell.YOUR_METHOD_OF_THIS_CELL()
return cell
case c3:
let cell = tableView.dequeueReusableCell(withIdentifier: "YOUR_IDENTIFIER") as? YOUR_CELL_CLASS_C2
cell.YOUR_METHOD_OF_THIS_CELL()
return cell
default:
debugPrint("That's all folks")
}
return UITableViewCell()
}
Hope this helps you!

cellForRow(at: ) returns nil

So I have this function.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier = "Cell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) as! customCell
changeCellProperty(selectedIndexPath: indexPath)
return cell;
}
func changeCellProperty(selectedIndexPath: IndexPath){
print("indexpath = \(selectedIndexPath)") . // printing [0,0] and all values
let cell = self.tableView.cellForRow(at: selectedIndexPath) as! customCell
// got nil while unwrapping error in above statement.
cell.label.text = ""
// and change other properties of cell.
}
I am not able to understand the error.
When I am getting the indexpath, then why I am not able to point a particular cell and change properties accordingly.
You cannot access a cell that has not yet been added to the tableView. That is what you are trying to do here in changeCellProperty method. So, if your dequeue works, then all you would need to do is pass the dequeued cell to that method.
func changeCellProperty(cell: customCell){
cell.label.text = ""
// and change other properties of cell.
}
Your cellForRowAt method would look like this.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier = "Cell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) as! customCell
changeCellProperty(cell: cell)
return cell
}
Note: class names should be UpperCamelCase. So your customCell should be named CustomCell.

cellForRowAt - Create and Return cell from within switch statement

I think I'm missing something fundamental to Swift, but can't find other examples of people doing what I'm trying:
Background
I have a UITableView with 2 prototype cells, with a different identifies, different features (label, image etc) and different classes.
I want the cellForRowAt function to return a different type and class of cell depending on the content in the array that holds the table data. That array is populated with struct instances, one characteristic of which identifies the type of cell that I want to represent the data.
Code Attempt
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch dataArray[indexPath.item].typeOfData {
case "Type1":
let cell = tableView.dequeueReusableCell(withIdentifier: "type1ReuseIdentifier", for: indexPath) as! type1Cell
//Set up the cell contents
return cell
case "Type2":
let cell = tableView.dequeueReusableCell(withIdentifier: "type2ReuseIdentifier", for: indexPath) as! type2Cell
//Set up the cell contents
return cell
default:
let cell = tableView.dequeueReusableCell(withIdentifier: "separatorIdentifier", for: indexPath) as! separatorCell
//Set up the cell contents
cell
}
}
What am I missing / doing wrong?
Edit:
It was missing the final return.
just do like this:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let typeSection = CellType(rawValue: indexPath.row)!
switch typeSection {
case .CenterTitleCell:
return getCenterTitleCell(tableView, indexPath)
case .CenterDescriptionCell:
return getCenterDescriptionCell(tableView, indexPath)
case .CenterImageCell:
return getImageCell(tableView, indexPath)
case .FooterTitleCell:
return getFooterViewCell(tableView, indexPath)
}
}
And use another method to return the Cell Type
func getCenterTitleCell (_ tableView: UITableView, _ indexPath:IndexPath) -> CenterTitleTableViewCell {
let cell:CenterTitleTableViewCell = tableView.dequeueReusableCell(withIdentifier: String(describing: CenterTitleTableViewCell.self),
for: indexPath) as! CenterTitleTableViewCell
cell.selectionStyle = .none
return cell
}

Cannot assign value of type 'UITableViewCell' to type '...Cell' error in swift

let cellIdentifier = "ChampionThumbnailCell"
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as? ChampionThumbnailTableViewCell
if cell == nil {
cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: cellIdentifier)
}
cell!.championNameLabel.text = championNames[indexPath.row]
cell!.championThumbnailImageView.image = UIImage(named: championThumbnail[indexPath.row])
return cell!
}
I want to use the above code to reuse UITableViewCell, but I got this error when build it.
It looks like thie: Cannot assign value of type 'UITableViewCell' to type 'ChampionThumbnailTableViewCell?'
Is there any solution could fix it?
(By the way, I'm not very good at English...)
Change your method to this:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier = "ChampionThumbnailCell"
var cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! ChampionThumbnailTableViewCell
cell.championNameLabel.text = championNames[indexPath.row]
cell.championThumbnailImageView.image = UIImage(named: championThumbnail[indexPath.row])
return cell
}
Notice in third line I am using as! instead of as? showing compiler that you aren't confused about your cell being nil.
But if it turns out that your cell is nil, it should cause runtime error.

Bound value in a conditional binding must be of Optional type [IOS - SWIFT]

I am trying to make a TO-DO list app in Xcode by using Swift, and I encounter an error writing one of the function methods on the "if let path = indexPath {" line which says "Bound value in a conditional binding must be of Optional type".
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
if let path = indexPath {
let currentString = dataSource[path.section][path.row]
cell.textLabel?.text = currentString
}
return cell
}
Because indexpath is not optional,you do not need to use conditional binding
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
let currentString = dataSource[indexPath.section][indexPath.row]
cell.textLabel?.text = currentString
return cell
}
why u want use two constant?
fix ure code:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel?.text = dataSource[indexPath.section][indexPath.row]
}
return cell
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel?.text = dataSource[indexPath.section][indexPath.row]
return cell
}
Use this code because I think my previous idea was not good.
You don't need conditional binding here as suggested by Leo.

Resources