Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this Swift code equivalent?

I'm populating the cells of a UITableView using the following code:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")! as UITableViewCell
    var someString:String
    cell.textLabel?.text = someString
    return cell
}

Playing around some more, I found I can accomplish the same task with this slightly different code:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as UITableViewCell!
    var someString:String
    cell?.textLabel?.text = someString
    return cell!
}

Xcode compiles and executes both pieces of code just fine. As a Swift newbie, it's been difficult absorbing optionals, and this kind of example just confuses me more. Can someone explain what's going on here? Is the code equivalent? And is one optional style more desirable than the other?

like image 443
steff Avatar asked Feb 27 '26 22:02

steff


1 Answers

They are similar but they are not the same.

What as does is to let the compiler know that you want to use an object as another.

In your example, tableView.dequeueReusableCell returns UITableViewCell?, which is an optional that can contain either nothing or UITableViewCell.

Optionals can be unwrapped in a few ways, either with if/let:

if let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") {
  // cell is a UITableViewCell here, not an optional
}
// cell doesn't exist here anymore

Using a guard

guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") else {
// cell is nil so it's not even created. We HAVE to exit here
return 
}
// cell is a cell is UITableView here, no optional

Or by forcing it, which is not safe and can cause your app to crash. (Personally I avoid these as much as I can, and only use them with IBOutlets)

let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")!
// cell will be UITableViewCell!, which is an optional that will
// crash if you try to use it and it's nil

Now back to your question, you have a UITableViewCell?, which is a regular optional.

In your first example, you are force-unwrapping it first with !, and then casting it to UITableViewCell. This will result in a UITableViewCell that is actually a force-unwrapped-optional, which will crash your app if it's nil and you try to use it.

In your second example, you are telling the compiler you want to use UITableViewCell? as UITableViewCell!, which will result in the same scenario.

In neither example you need to use ? or ! when using cell, since it's already force-unwrapped.

I would, however, suggest you use a guard to avoid using force-unwrapped-optionals. This is how I handle custom cells:

guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as? CustomCell else {
  fatalError("CustomCell is not in the table view")
  // Crash with a custom message instead of a generic one
}

Note that I'm using tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath), this method doesn't return an optional, so if you want to use a cell that doesn't have a custom class, you can use this and don't have to worry about unwrapping.

like image 68
EmilioPelaez Avatar answered Mar 02 '26 12:03

EmilioPelaez



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!