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.
Related
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!
I'm trying to get the text on a table view cell and then get the index of it in an array.
This is the code I'm using:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as UITableViewCell
let indexOfCellString = event.index(of: cell.textLabel!.text)
}
But I get the following errors:
value of optional type string? not unwrapped
invalid character in source file
What is going on here? What else do I need to unwrap?
There is no need to cast dequeueReusableCell to UITableViewCell since that is its return type.
cell.textLabel is optional. And then the text property of UILabel is optional.
Properly deal with optionals:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
if let text = cell.textLabel?.text {
let indexOfCellString = event.index(text)
// do stuff with indexOfCellString
}
return cell
}
In my tableView I can toggle between two cell classes depending on layout. So now I wonder how I can choose what cell class to select in the didEndDisplaying function.
Should I choose cell by using dequeueReusableCell like in the function bellow?
func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if isBigCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CellBig") as! BigTableViewCell
cell.myImageView.kf.cancelDownloadTask()
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "CellSmall") as! SmallTableViewCell
cell.myImageView.kf.cancelDownloadTask()
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if isBigCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CellBig") as! BigTableViewCell
let data = ads[(indexPath as NSIndexPath).row]
cell.configureWithData(data)
//Dont show highlight
cell.selectionStyle = UITableViewCellSelectionStyle.none
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "CellSmall") as! SmallTableViewCell
let data = ads[(indexPath as NSIndexPath).row]
cell.configureWithData(data)
//Dont show highlight
cell.selectionStyle = UITableViewCellSelectionStyle.none
return cell
}
}
The cell is given to you in the didEndDisplaying method. You determine its real type based on the indexPath, just like you did in the cellForRowAt method.
Do not dequeue another cell in didEndDisplaying. Just cast the provided cell based on the indexPath.
Since it seems that you don't use indexPath to determine then cell type, then your code should be something like this:
func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if isBigCell {
if let bigcell = cell as? BigTableViewCell {
bigcell.myImageView.kf.cancelDownloadTask()
}
} else {
if let smallcell = cell as? SmallTableViewCell {
smallcell.myImageView.kf.cancelDownloadTask()
}
}
}
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.
I am trying to change an image within a cell when it is selected. Here is what I have in my view controller:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! CustomTableViewCell
cell.bgImage.image = UIImage(named: "second_image")
}
This is where I set the image:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! CustomTableViewCell
cell.bgImage.image = UIImage(named: "first_image")
}
When I select the cell, the image does not update. How do I get this to work?
The issue is probably that you are calling dequeueReusableCellWithIdentifier. Try using cellForRowAtIndexPath instead (documentation about it here). This will give you a reference to the current cell, rather than a reference to a new reusable cell.
So, according to your code above:
let cell = self.tableView.cellForRowAtIndexPath(indexPath) as! CustomTableViewCell
This typecast is critical because cellForRowAtIndexPath returns UITableViewCell, which will not have the bgImage member.
Also, make sure that you have a member called bgImage that is a UIImageView in your CustomTableViewCell class by adding #IBOutlet strong var bgImage: UIImageView!, and that said IBOutlet is connected in your storyboard/xib.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath) as! CustomTableViewCell
cell.bgImage.image = UIImage(named: "second_image")}
For Swift 3+:
func tableView(tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! CustomTableViewCell
cell.bgImage.image = UIImage(named: "second_image")}
Change your didSelectRowAtIndexPath to:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath)
cell.bgImage.image = UIImage(named: "second_image")
}
As per default this works to change the image
let cell = tableView.cellForRowAtIndexPath(indexPath)
cell!.imageView?.image = UIImage(named: "2")
Though it is too late. But i like to answer to participate in this world.
I was having problem with changing selected and deselected cell image of a table view. I solved it this way.
When tableview delegate method call then create instance of that cell by
let cell = self.tableView.cellForRow(at: indexPath) as! CustomeCell
instead of
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomeCell
and use your desired image into your cell imageview.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = self.tableView.cellForRow(at: indexPath) as! CustomeCell
if indexPath.row == 0
cell.btnImageView.image = UIImage.init(named: "screenr.png")
}
override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
let cell = self.tableView.cellForRow(at: indexPath) as! CustomeCell
if indexPath.row == 0
cell.btnImageView.image = UIImage.init(named: "screen.png")
}
Can't you simply use the .hightlightedimage value for the imageView? I'm doing the following in my cellForRowAt func:
cell.imageView?.image = UIImage(named: "\(indexPath.row).png")
cell.imageView?.highlightedImage = UIImage(named: "\(indexPath.row)g.png")
And I've just named the necessary images "0.png" and "0g.png" etc to make sure the image and highlighted image match up. Of course, that's a small static array, if you were using coreData with a larger array you could simply hold the imageName and the hightlightedImageName in the data set and pull the info from there.