Select what cell class to use in didEndDisplaying - ios

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()
}
}
}

Related

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.

How do I proceed on adding multiple prototype cell's

I'm trying to add two prototype cell on my UITableView. However, I don't know how I could verify to be able to "return" the correct cells for each prototype. Can you guys give me a hand?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if ??? {
let cell = itensTableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! tableviewCell
cell.nameCell.text = "Oculos"
return cell
}else{
let cellAdicionar = itensTableView.dequeueReusableCell(withIdentifier: "cellIdAdc", for: indexPath) as! tableviewBotaoAdicionar
cellAdicionar.botaoAdicionar.text = "Adicionar"
return cellAdicionar
}
}
Storyboard Picture
You need to set your model to answer that inside cellForRowAt
var arr = ["first","second","first"]
//
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let item = arr[indexPath.row]
if item == "first" {
let cell = itensTableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! tableviewCell
cell.nameCell.text = "Oculos"
return cell
} else {
let cellAdicionar = itensTableView.dequeueReusableCell(withIdentifier: "cellIdAdc", for: indexPath) as! tableviewBotaoAdicionar
cellAdicionar.botaoAdicionar.text = "Adicionar"
return cellAdicionar
}
}

array.index (of: ) not working properly

I'm trying to find a UITableViewCell text in an array. The problem is no matter what cell I'm clicking on, array.index(of:) always returns 1.
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(of: text)
print (indexOfCellString!)
}
}
//here is my attempt to set the cell text:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
if eventIndex.indices.contains(indexPath.row) == true {
cell.textLabel?.text = event [indexPath.row]
}
return cell
}
event is an array that i'm trying to search in and find cell's text.
and cell's text is always in an index of event. because my tableview reads the information from event array. therefore it shouldn't always return 1.
What am I doing wrong?
Never use dequeueReusableCell outside of cellForRowAt. Simply access your data from your data model.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if eventIndex.indices.contains(indexPath.row) == true {
let text = event[indexPath.row]
if let indexOfCellString = event.index(of: text) {
print("Found index: \(indexOfCellString)")
} else {
print("text not found")
}
}
}

CheckBox on tableview duplicating, Swift, iOS

I have a tableView that when selected changes an image from one to another. This all works fine but when I select a tableCell it changes the image, but when I scroll it has also changed the image of another cell that I didn't select.
Below is my code.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "FeaturesCell") as! FeaturesCell
cell.featuresLabel.text = self.items[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
pickedFeatures.append(items[indexPath.row])
let cell = tableView.cellForRow(at: indexPath) as! FeaturesCell
cell.checkImage.image = #imageLiteral(resourceName: "tick-inside-circle")
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
pickedFeatures.remove(at: pickedFeatures.index(of: items[indexPath.row])!)
let cell = tableView.cellForRow(at: indexPath) as! FeaturesCell
cell.checkImage.image = #imageLiteral(resourceName: "No-tick-inside-circle")
}
If I use detqueureusable cell in the did select function then it just doesn't change the picture at all when selected.
You can use tableView.dequeueReusableCell(_), The problem is, you didn't maintain the status of the selected cells.
Example :
class viewController: UIVieWController, UITableViewDelegate, UITableViewDataSource {
var selectedCellList = [IndexPath]()
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "FeaturesCell") as! FeaturesCell
cell.featuresLabel.text = self.items[indexPath.row]
if let _ = selectedCellList.index(of: indexPath) {
// Cell selected, update check box image with tick mark
cell.checkImage.image = #imageLiteral(resourceName: "tick-inside-circle")
} else {
// Cell note selected, update check box image without tick mark
cell.checkImage.image = #imageLiteral(resourceName: "No-tick-inside-circle")
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
pickedFeatures.append(items[indexPath.row])
if let index = selectedCellList.index(of: indexPath) {
selectedCellList.remove(at: index)
} else {
selectedCellList.append(indexPath)
}
tableView .reloadRows(at: [indexPath], with: .automatic)
}
}

How do I have a single select and a multiselect in my tableview?

in my cellForRowAt Im inflating my xib and setting its content:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: TableViewCell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath) as! TableViewCell
cell.label.text = data[indexPath.row]
let tap = UIGestureRecognizer(target: self, action: #selector(tableCellTap(_:cell:)))
cell.addGestureRecognizer(tap)
cell.selectionStyle = .none
cell.checkBox.isUserInteractionEnabled = false
cell.checkBox.boxType = .circle
cell.checkBox.markType = .radio
cell.checkBox.cornerRadius = 0
cell.checkBox.stateChangeAnimation = .expand(.fill)
if (indexPath.row == selectedIndex){
cell.checkBox.checkState = .checked
}else{
cell.checkBox.checkState = .unchecked
}
return cell
}
Then Im setting my deselect and select values
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! TableViewCell
cell.checkBox.checkState = .checked
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! TableViewCell
cell.checkBox.checkState = .unchecked
}
I need a sense of direction in how i can make it select and deselect the same row and update my xib file checkbox?
m13checkbox is being used
when i click on the cell for the first time it selects it but when i click on the same cell again it does not call it and does nothing until a loop a completed in the checkboxes
you don't need didDeselectRowAt, you can achieve the same functionality by checking if the radio button is checked in your didSelectRowAt.
If the radio button is checked, simply uncheck it and vice versa.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! TableViewCell
if(cell.checkBox.isChecked){
cell.checkBox.checkState = .unchecked
}else{
cell.checkBox.checkState = .checked
}
}
Apple has already given very good sample code for that on its website,
you can check at:https://developer.apple.com/library/content/samplecode/TableMultiSelect/Introduction/Intro.html

Resources