Swift Convert Optional String to Int or Int32 (Unwrapping optionals question)

908 views Asked by At

I am trying to read a string and convert it to an int. I have a solution but it seems way too complicated. I guess I am still trying to wrap my head around unwrapping.

I have posted code below along with the compiler errors that I get with each solution.

In this example I try to read a string from UserDefaults and convert to an integer value.

static func GetSelectedSessionNum() -> Int32 {
    var sessionNum : Int32 = 0
    let defaults = UserDefaults.standard

    let optionalString: String? = defaults.string(forKey: "selectedSessionNum")
    // this works but it's too complicated
    if let string = optionalString, let myInt = Int32(string) {
        return myInt
    }
    return 0

    // Error : optional String? must be unwrapped to a value of type 'String'
    let t : String = defaults.string(forKey: "selectedSessionNum")

    if let s : String = defaults.string(forKey: "selectedSessionNum") {
        // error - Int32? must be unwrapped to a value of Int32
        return Int32(s)
    }
    return 0
}
3

There are 3 answers

0
Gustavo Vollbrecht On

You need to cast to non optional Int32 in order to match your return type.

You can use any optional binding approach, or change your return type to Int32?

4
vadian On

If you want an uncomplicated solution save selectedSessionNum as Int

static func getSelectedSessionNum() -> Int32 {    
    return Int32(UserDefaults.standard.integer(forKey: "selectedSessionNum"))
}

otherwise double optional binding

if let string = UserDefaults.standard.string(forKey: "selectedSessionNum"), let myInt = Int32(string) {
    return myInt
}

or the nil coalescing operator

if let string = UserDefaults.standard.string(forKey: "selectedSessionNum") {
    return Int32(string) ?? 0
}

is the proper way

0
Cristik On

If you want to avoid optional bindings, you can use flatMap, when called on Optional's it allows you to convert one optional to another:

return UserDefaults.standard.string(forKey: "selectedSessionNum").flatMap(Int32.init) ?? 0

You'd also need the ?? (nil coalescing operator) to cover the scenarios where either the initializer fails, or the value is not present in user defaults.