kuemme01 kuemme01 - 3 months ago 26
Swift Question

Variable use of multiple custom cells

I'm using a unclickable tableView to display different information of one object.
For this informations I have different custom cell types one where I placed a map, if my object have locations, one have a list with links, and another a multiple line label for a little description...for example.

I manage this cells with:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

if indexPath.row == 0 {
let cell: mapCell = tableView.dequeueReusableCellWithIdentifier("mapCell") as! MapCell
return cell
} else if indexPath.row == 1 {
let cell: textCell = tableView.dequeueReusableCellWithIdentifier("textCell") as! TextCell
return cell
} else if indexPath.row == 2 {
let cell: listCell = tableView.dequeueReusableCellWithIdentifier("listCell") as! ListCell
return cell
}

}


So far so good, everything working fine. My problem is, not every object needs a map, some of them just need some text and a list, other objects need a map and a list, other all of them. I want my tableView to skip some cells if there is a condition.

I know, I can make an symbolic array for changing the number of cells of my tableView, but that deleting just from the end of my tableView, not specific cells.

One of my ideas is to generate a empty cell, maybe with a height of 0 or 1 so that I can do something like this:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

if indexPath.row == 0 {
if mapCellNeeded {
let cell: mapCell = tableView.dequeueReusableCellWithIdentifier("mapCell") as! mapCell
} else {
let cell: emptyCell = tableView.dequeueReusableCellWithIdentifier("emptyCell") as! EmptyCell
}
return cell
} else if indexPath.row == 1 {
...
}...
}


put I don't know if there isn't an efficient way. Hope you guys can help me.

Answer

Your solution would work. Another approach (very nice and swifty) would be not to hardcode row numbers, but rather use enum instead:

enum InfoCellType {
case Map
case Text
case Links
}

... 

var rows = [InfoCellType]()
... 
// when you know what should be there or not
func constructRows() {

if (mapCellNeeded) {
rows.append(InfoCellType.Map)
}
rows.append(InfoCellType.Text)
... etc
}

Then in the table view methods just see what's the type for current indexPath:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

let cellType: InfoCellType = self.rows[indexPath.row]
switch cellType {
case .Map:
    let cell: mapCell = tableView.dequeueReusableCellWithIdentifier("mapCell") as! mapCell 
    return cell
case .Text:
    ...
case.Links:
    ...
}
}

This solution also allows to easily change order of rows - just change the order of items in rows array.