Swift safely unwrapping optinal strings and ints
Asked Answered
P

5

8

When I am about to fire my segue for the 2nd view I also send some values like this:

if let aTime = ads[indexPath.row]["unix_t"].int {
    toView.time = aTime
}

if let aTitle = ads[indexPath.row]["title"].string {
    toView.title = aTitle
}

In the second VC I have declared the varibles like:

var time: Int?
var title: String?

and this is how I unwrap the values:

if time != nil {
   timeLabel.text = String(time!)
}

if title != nil {
   titleLabel.text = title!
}

This all works I never get any error caused by unwrapped varibles or nil values. But is there any easier way to do it?

Right now it feels like I am checking too much

Parlour answered 27/6, 2016 at 18:53 Comment(0)
L
12

I can think of three alternatives.

  1. if/let. Very similar to your current option, but you don't have to implicitly unwrap.

    if let time = time {
        timeLabel.text = "\(time)"
    }
    
    if let title = title {
        titleLabel.text = title
    }
    

    You can even unwrap them on the same line. The downside to this is that if one of them is nil, then neither label will be set.

    if let time = time, let title = title {
        timeLabel.text = "\(time)"
        titleLabel.text = title
    }
    
  2. guard/let. If these are in a function like setupViews(), then you can one-line your unwrapping like so:

    func setupViews() {
        guard let time = time, let title = title else { return }
        timeLabel.text = "\(time)"
        titleLabel.text = title
    }
    
  3. You can use default values and the ?? operator to unwrap quickly.

    timeLabel.text = "\(time ?? 0)"
    titleLabel.text = title ?? ""
    
Lyricist answered 27/6, 2016 at 19:5 Comment(1)
For a 4th and 5th alternative, see vadian's answer and Martin R's comment to the question.Lyricist
D
8

You can use the Nil Coalescing Operator too as given in the Docs:

The nil coalescing operator (a ?? b) unwraps an optional a if it contains a value, or returns a default value b if a is nil. The expression a is always of an optional type. The expression b must match the type that is stored inside a.

The nil coalescing operator is shorthand for the code below:

a != nil ? a! : b

Ducat answered 27/6, 2016 at 19:9 Comment(0)
A
2
if let time = time {
    timeLabel.text = "\(time)"
}

if let title = title {
    titleLabel.text = title
}

It's the same as with your JSON

Aylsworth answered 27/6, 2016 at 18:57 Comment(0)
V
1

Yes, you are checking too much (twice).

Since only non-optional values are passed you can declare the variables non-optional

var time = 0
var title = ""

and set the labels

timeLabel.text = "\(time)"
titleLabel.text = title

The strong type system of Swift highly recommends first to consider

Can I accomplish this without optionals?

and – if there is no other option – then use optionals.

Volant answered 27/6, 2016 at 18:59 Comment(3)
You mean giving them "dummy" values in the second VC? So that it will fallback to the dummy values in case no value was never passed in the segueParlour
@Parlour You have to decide how to handle errors. If not-passing a value is valid, then use an optional. If not passing a value should be considered an error, then you can just use forced-unwrapping without checking.Enosis
If this solution suits your design, yesVolant
O
1

You don't need to check nil condition in the first view. Please follow below code:

toView.time = ads[indexPath.row]["unix_t"] as? Int

toView.title = ads[indexPath.row]["title"] as? String

time and title variable in second view are optionals. So, when you assign a value to toView.time and toView.title, it will either assign the value of type time and title respectively or nil.

Octaviooctavius answered 27/6, 2016 at 19:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.