Guard Not Unwrapping Optional

Guard not unwrapping optional

try? JSONSerialization.jsonObject(with: data) as? [String:Any]

is interpreted as

try? (JSONSerialization.jsonObject(with: data) as? [String:Any])

which makes it a "double optional" of type [String:Any]??.
The optional binding removes only one level, so that json has
the type [String:Any]?

The problem is solved by setting parentheses:

guard let json = (try? JSONSerialization.jsonObject(with: data)) as? [String:Any] else {
break
}

And just for fun: Another (less obvious?, obfuscating?) solution is to
use pattern matching with a double optional pattern:

guard case let json?? = try? JSONSerialization.jsonObject(with: data) as? [String:Any] else {
break
}

Swift why unwrapping optional by guarding against NIL is not working

The type of s is still Optional, so whether you did a nil check or not is irrelevant. The nil check is done in runtime, while the type system is doing a compile-time check. The only way to ensure s can never be nil is via optional binding if let or guard let.

swift - unwrapping optional with guard let

It doesn’t make much sense to force unwrap the optional in a conditional let assingment. Remove the !:

guard let articleTitle = self.articles?[indexPath.row]["title"].string else {return}

Otherwise the right-hand side will never produce nil but crash.

Not using unwrapping in guard statements

guard let unwrapped = optional is an Optional Binding (no link available directly to the correct book section, unfortunately). It safely tries to unwrap the value in the optional. If there is a value, the unwrap succeeds, and the value is assigned to the given name.

You should heavily favor the use of optional bindings, with either guard or if (the difference is the scope of the "unwrapped" name) over the use of forced unwrapping with !. A failed force unwrap is a fatal error; your program will simply crash.

Safely unwrapping optional with guard let in init()

Store the result as a property of your objects. Better yet, use a static property, not a global.

class iCloudManager {
static let defaultPath = FileManager.default.url(forUbiquityContainerIdentifier: nil)?.appendingPathComponent("Documents")

let path: URL

init?() {
guard let path = iCloudManager.defaultPath else { return nil }
self.path = path
}

func function1() {
// uses self.path
}

func function2() {
// uses self.path
}
}

Unwrapping optionals to a pre-defined variable in the guard condition without creating a new constant

I would just test for nil and then force unwrap when I know it's not:

var someString: String? = "hello"
let nonOptionalString: String // note, you don't have to initialize this with some bogus value

guard someString != nil else { return }
nonOptionalString = someString!

Or if someString was a parameter to some method or closure, you can unwrap in the guard statement using the same variable name, simplifying life even more:

func foo(someString: String?) {
guard let someString = someString else { return }

// now I can just use local `someString`, which is not optional anymore
}

If you're desperate to unwrap and exit-if-nil in a single statement, you could theoretically write a function to unwrap if it can or throw an error if it can't:

extension Optional {
enum OptionalError: Error {
case unwrapFailed
}

func unwrap<T>() throws -> T {
if self == nil { throw OptionalError.unwrapFailed }
return self as! T
}
}

Then you can do:

do {
firstNonOptional = try firstOptional.unwrap()
secondNonOptional = try secondOptional.unwrap()
thirdNonOptional = try thirdOptional.unwrap()
} catch {
return
}

I think that's horrible overkill, but if you're desperate to distill it down to one line per unwrap, that's one way to do it.

Use guard with double-optional

You can use Guard as well as if let

if let getValue = something, let value = getValue {
print(value)
}

guard let getValue = something , let value = getValue else {
return
}

You can also use FlatMap

if let value = something.flatMap({ $0 }) {
print(value)
}

If you have any level of optionals e.g 3,4,5,7 you will get the value with Conditionally cast

  let something: Bool????? = true
if let value = something as? Bool {
print(value) // prints true
}

Although use of guard let, not unwrapped error

You have to optional downcast all dictionaries to the proper type

guard let json = try NSJSONSerialization.JSONObjectWithData(tickerData, options: []) as? [String:AnyObject] else { return nil }
guard let tableauUn = json["result"] as? [String:AnyObject] else {return nil }
guard let tableauDeux = tableauUn["XXBTZEUR"] as? [String:AnyObject] else { return nil}

and the final value

let prix = tableauDeux["o"] as? String

using guard to check for nil without implicitly unwrapping

In your guard code you would have to have a return statement in the else block. Like this...

guard json["error"] == nil else {
let error = json["error"]!
// handle error
return
}

// handle success

But you are correct. Having to force unwrap the error is not ideal.

So in this case. I think guard is the wrong solution. Instead use if but return from the conditional block. This removes the need for using an else block.

if let error = json["error"] {
print(error)
// handle error
return
}

// handle success...
// no need for else block. Just return from the if in the error case.

The difference between guard let and if let is where the unwrapped optional is scoped.

With guard it is scoped outside the block with if it is scoped inside the block.

After guard let url the value still needs to be unwrapped

urls is actually of type [String: URL?]. Note that the value type is optional, because URL.init(string:) is failable.

When you try to get a value from this dictionary, you get a URL??. The guard only unwraps one layer of the optional.

One way to unwrap a nested optional (no matter how many layers), is to use as?:

guard let url = urls["en"] as? URL else { return }


Related Topics



Leave a reply



Submit