iOS tableView with two special rows of headers Using swift for iOS, here is my cellforRow method

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&gt; UITableViewCell {   
    switch indexPath.section {
    case 0: // Cover Image
        guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifierCover) as? AddBlogCoverTableViewCell else { return UITableViewCell() }
        cell.layer.backgroundColor = UIColor.clear.cgColor
        cell.selectionStyle = .none
        cell.indexPath = indexPath
        cell.delegate = self
        cell.titleTextField.delegate = self
        cell.coverImageView.image = coverImage
        cell.titleTextField.placeholder = "Title"
        cell.titleTextField?.text = articleName ?? ""
        cell.setBorder(of: 0.7, ofColor: UIColor.lightGray.cgColor)

        return cell

    case 1: // rest story
        guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) as? AddBlogTableViewCell else { return UITableViewCell() }
        cell.layer.backgroundColor = UIColor.clear.cgColor
        cell.selectionStyle = .none
        cell.indexPath = indexPath
        cell.delegate = self
        cell.captionTextView.delegate = self
        cell.captionTextView.tag = indexPath.row
        cell.tag = indexPath.section
        cell.media = cards?[indexPath.row].media
        cell.captionTextView.text = cards?[indexPath.row].caption ?? ""
        showLocationSuggestions(at: indexPath, in: cell)
        cell.poi = cards?[indexPath.row].poi
        return cell
    default:
        return UITableViewCell()
    }
    return UITableViewCell()
}


How should I avoid repeating the code that I have to provide to the cell in all cases of switch?
Defensive programming (never force unwrap, no forced cast, ...) is good
and important to handle "runtime problems" gracefully: Unexpected user
input, failed network connections, I/O errors, and many more.

But programming errors are a different category. Example 1: If 

tableView.dequeueReusableCell(withIdentifier: cellIdentifierCover)


fails, or does not return a AddBlogCoverTableViewCell, then you did
not configure the table view correctly in the Storyboard. Such cases
should be detected during development. Therefore it is better to abort
with a runtime error instead of "hiding" the problem and returning
a plain UITableViewCell. This is a valid use-case for a forced cast:

 let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifierCover) as! AddBlogCoverTableViewCell


or better:

let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifierCover, for: indexPath) as! AddBlogCoverTableViewCell


Example 2: Your table view has 2 sections, so indexPath.section must be 0 or 1, every other value would be a programming error.
Again, fail early instead of hiding the problem:

switch indexPath.section {
case 0:
    // do something ...
case 1:
    // do something ...
default:
    fatalError("Unexpected section \(indexPath.section)")
}


Note also that your final

return UITableViewCell()


is never be executed.



Now for possible simplifications. Both cell classes have some properties
in common, these can be defined in a common superclass:

class AddBlogCommonCell : UITableViewCell {
    var indexPath: IndexPath!
    var delegate: UITableViewController!
    // ...
}

class AddBlogCoverTableViewCell : AddBlogCommonCell {
    // ...
}

class AddBlogTableViewCell : AddBlogCommonCell {
    // ...
}


Then you can configure the specific properties inside the switch
statement, and the shared properties outside the switch statement,
thereby avoiding the code repetition:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&gt; UITableViewCell {

    let cell: AddBlogCommonCell
    switch indexPath.section {
    case 0:
        let coverCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifierCover) as! AddBlogCoverTableViewCell
        coverCell.titleTextField.delegate = self
        coverCell.coverImageView.image = coverImage
        // ...
        cell = coverCell
    case 1:
        let storyCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) as! AddBlogTableViewCell
        storyCell.captionTextView.delegate = self
        storyCell.captionTextView.tag = indexPath.row
        // ...
        cell = storyCell
    default:
        fatalError("Unexpected section \(indexPath.section)")
    }

    // AddBlogCommonCell properties:
    cell.delegate = self
    cell.indexPath = indexPath
    // ...

    // UITableViewCell properties:
    cell.layer.backgroundColor = UIColor.clear.cgColor
    cell.selectionStyle = .none
    // ...

    return cell
}