1

Given an optional var pinImageView: UIImageView? which has properties that are set, I'm not sure which way is preferred to set the property. For example:

if let image = UIImage(named: "Pin") {
    pinImageView = UIImageView(image: image)
    pinImageView?.restorationIdentifier = "pin"
}

or

if let image = UIImage(named: "Pin") {
    pinImageView = UIImageView(image: image)
    pinImageView!.restorationIdentifier = "pin"
}
pacification
  • 5,838
  • 4
  • 29
  • 51
bhartsb
  • 1,316
  • 14
  • 39
  • The answer to _which is preferred_ can be Opinion based when there's no widely accepted way. This site seems not appropriate to gather such opinions. – OOPer Jul 15 '18 at 05:06
  • Force unwrap(`!`) is always discouraged as it can crash your app. In the above example although `pinImageView` is initialized just before using the force unwrap(`!`) on it and it will work as expected with both approaches above but still i would recommend the first approach. Avoid making habit to a problematic approach. – Kamran Jul 15 '18 at 05:10
  • @OOPer How would I know in advance for sure that this question is opinion based? One way might be considered wrong. – bhartsb Jul 15 '18 at 05:35
  • Maybe when your question is closed. – OOPer Jul 15 '18 at 05:37
  • 1
    There's a third option, too:`if let image = UIImage(named: "Pin"), let view = UIImageView(image: image) { view.restorationIdentifier = "pin" }` – NRitH Jul 15 '18 at 06:07
  • I would use a local non optional variable – Sulthan Jul 15 '18 at 10:40
  • 1
    @Kamran `!` *is not* discouraged. It has legitimate use cases. Sometimes you just cannot handle the case any other way. It's not a good idea to claim that your app won't crash but create undefined app behaviors instead. Also, often I see people avoiding `!` but still adding `fatalError()` all over their code. – Sulthan Jul 15 '18 at 10:44

2 Answers2

2

which way is preferred

It is generally accepted that you should avoid ! (force unwrapping) which is just begging for a crash, so this use should be avoided:

if let image = UIImage(named: "Pin") {
    pinImageView = UIImageView(image: image)
    pinImageView!.restorationIdentifier = "pin"
}

In this case, since you've just assigned pinImageView, force unwrapping it is safe, but it still raises red flags to you or anyone else who reads your code in the future. "Ugh, they're using force unwrap here. Could that crash? Well, could pinImageView be nil? No, it was just assigned in the previous line, so it's OK." Why put yourself and others through this thought process; avoid the ! whenever possible.

This usage:

if let image = UIImage(named: "Pin") {
    pinImageView = UIImageView(image: image)
    pinImageView?.restorationIdentifier = "pin"
}

is safer because it uses optional chaining to unwrap pinImageView and avoids the crash operator !, but it still unwrapping an optional variable.

A third alternative:

The reason the imageView is optional is that you've assigned it to an optional variable. If instead, you use a let constant to hold the object while you configure it, you can avoid filling your code with unwrapping code:

if let image = UIImage(named: "Pin") {
    let imageView = UIImageView(image: image)
    imageView.restorationIdentifier = "pin"
    pinImageView = imageView
}

This method works well when you are assigning many properties to the object since you can avoid many unwrapping operators.

Don't worry about the extra line of code. The compiler will optimize that out. Code for readability and clarity.

vacawama
  • 150,663
  • 30
  • 266
  • 294
  • would you say that the second optional chaining way is fine when there is only one property getting assigned? – bhartsb Jul 16 '18 at 00:09
  • @bhartsb, it is fine. I'd probably do that if assigning just a single property. But by the time you're assigning two or three, the optional chaining starts to stand out. – vacawama Jul 16 '18 at 01:21
0

We have a code style/review rule in our team along the lines of "No use of the ! operator without a comment describing why it's safe".

Because ! destroys all the advantages of nil-safety in Swift, and casual use of it is asking for crashes and drags the language back to C/C++/Java/C#/Javascript/etc NullPointerException hell.

So in your case the

pinImageView?.restorationIdentifier = "pin"

option would definitely be preferred.

Jon N
  • 1,439
  • 1
  • 18
  • 29