Shyam Shyam - 2 months ago 10
Swift Question

Multiple implementation of custom uitableviewcell using dynamic prototype cells

Three different, dynamic prototype tableviewcells are used in my project.

Two are stock cells(basic with different options), and one is a custom cell. And this, may change as required.

The problem I face is while dequeuing the cells.

If they are done normally as UITableViewCells, I'm not able to use my custom cell outlets or actions.

let cell = tableView.dequeueReusableCellWithIdentifier(identifier, forIndexPath: indexPath)


And, If they are done the other way, the app crashes with the below error.

let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! SwitchTableViewCell


Error:

Could not cast value of type 'UITableViewCell' (0x38595c58) to 'AppName.SwitchTableViewCell' (0x13cdf8).


Below is the implementation of
cellForRowAtIndexPath
method,

// MARK: - UITableViewDelegate Methods

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// Setup a cellIdentifer string to store the cell reuse identifier you want to use for each row.
var cellIdentifier: String

// Switch through each row and set the appropriate cell reuse identifier
switch sections[indexPath.section].items[indexPath.row] {
case .AudioDevices, .Acknowledgments:
cellIdentifier = "DisclosureCell"
case .AllowNotifications, .ShowCloudMusic:
cellIdentifier = "SwitchCell"
case .Version:
cellIdentifier = "RightDetailCell"
}

// Populate your cell reuse identifier into the cell

if cellIdentifier == "SwitchCell" {
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! SwitchTableViewCell
return cell
} else {
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath)
return cell
}

// Switch through each cell, and implement the labels/setup for each row
// The order of the cases is irrelevant!
switch sections[indexPath.section].items[indexPath.row] {
case .AudioDevices:
cell.textLabel?.text = "Audio Devices"
cell.detailTextLabel?.text = String(userDefaults.integerForKey(audioDeviceListKey))
case .AllowNotifications:
cell.switchCellLabel?.text = "Allow Notifications"
cell.userInteractionEnabled = false
case .ShowCloudMusic:
cell.switchCellLabel?.text = "Show Cloud Music"
case .Acknowledgments:
cell.textLabel?.text = "Acknowledgements"
cell.detailTextLabel?.text = ""
case .Version:
cell.textLabel?.text = "Version"
cell.detailTextLabel?.text = buildVersion
cell.detailTextLabel?.textColor = UIColor.lightGrayColor()
cell.userInteractionEnabled = false
}
// Return the cell
return cell
}


Screenshot:

Image

Answer

To use multiple kinds of cell in Table View, you have to put some condition to check to see which cell be used for certain condition.

func tableView cellForRowAtInd....... {
    //depends on what base you separate both cells 
    if condition = true { 
        let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! SwitchTableViewCell
        return cell
    } else {
        let cell = tableView.dequeueReusableCellWithIdentifier(identifier, forIndexPath: indexPath)
       return cell
    }

}

Update based upon your cellForRowAtIndexPath code:

You are already returning before cell before your other part of code run. Hence the cell is already returned and its of no use for other part of code.

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    // Setup a cellIdentifer string to store the cell reuse identifier you want to use for each row.
    var cellIdentifier: String

    // Switch through each row and set the appropriate cell reuse identifier
    switch sections[indexPath.section].items[indexPath.row] {
    case .AudioDevices, .Acknowledgments:
        cellIdentifier = "DisclosureCell"
    case .AllowNotifications, .ShowCloudMusic:
        cellIdentifier = "SwitchCell"
    case .Version:
        cellIdentifier = "RightDetailCell"
    }

    // Populate your cell reuse identifier into the cell

    if cellIdentifier == "SwitchCell" {
        let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! SwitchTableViewCell

        // Switch through each cell, and implement the labels/setup for each row
        // The order of the cases is irrelevant!
        switch sections[indexPath.section].items[indexPath.row] {
        case .AudioDevices:
            cell.textLabel?.text = "Audio Devices"
            cell.detailTextLabel?.text = String(userDefaults.integerForKey(audioDeviceListKey))
        case .AllowNotifications:
            cell.switchCellLabel?.text = "Allow Notifications"
            cell.userInteractionEnabled = false
        case .ShowCloudMusic:
            cell.switchCellLabel?.text = "Show Cloud Music"
        case .Acknowledgments:
            cell.textLabel?.text = "Acknowledgements"
            cell.detailTextLabel?.text = ""
        case .Version:
            cell.textLabel?.text = "Version"
            cell.detailTextLabel?.text = buildVersion
            cell.detailTextLabel?.textColor = UIColor.lightGrayColor()
            cell.userInteractionEnabled = false
        }
        // Return the cell
        return cell
    } else {
        let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath)

        // Switch through each cell, and implement the labels/setup for each row
        // The order of the cases is irrelevant!
        switch sections[indexPath.section].items[indexPath.row] {
        case .AudioDevices:
            cell.textLabel?.text = "Audio Devices"
            cell.detailTextLabel?.text = String(userDefaults.integerForKey(audioDeviceListKey))
        case .AllowNotifications:
            cell.switchCellLabel?.text = "Allow Notifications"
            cell.userInteractionEnabled = false
        case .ShowCloudMusic:
            cell.switchCellLabel?.text = "Show Cloud Music"
        case .Acknowledgments:
            cell.textLabel?.text = "Acknowledgements"
            cell.detailTextLabel?.text = ""
        case .Version:
            cell.textLabel?.text = "Version"
            cell.detailTextLabel?.text = buildVersion
            cell.detailTextLabel?.textColor = UIColor.lightGrayColor()
            cell.userInteractionEnabled = false
        }
        // Return the cell
        return cell
    }
}