Reputation: 16256
I'm guard
ing the call to a method that may throw (a CoreData fetch request), and at the same time I'm casting the returned value to a specific type of array:
guard let results = try? managedContext.executeFetchRequest(fetchRequest) as? [MyManagedObjectClass] else {
// Bail out if fetch or cast fails:
return
}
The way I understand it is that, because I'm using guard/try?/else
(instead of do/try/catch
), the else
block (i.e. return
statement) above will be executed if either of the following occurs:
throw
s)[MyManagedObjectClass]
fails.The code above works, but the after control successfully passes the guard
check, the variable results
ends up as being of type [MyManagedObjectClass]?
("optional array of MyManagedObjectClass
").
So if I want to -say- loop through the array elements I have to first unwrap it:
if let results = results {
// now, 'results' is of type:
// "(non-optional) Array of MyManagedObjectClass"
for element in results {
// (process each element...)
}
}
I could use as!
instead of as?
when casting after the guard
statement; that makes results
a non-optional array.
But then, if the fetch succeeds but the cast fails, It will still trigger a runtime error (crash) instead of control flowing to the else
block, right?.
Is there a smarter way? (catch both errors, end up with a non-optional array)
Note: I understand that lumping both failure causes (fetch and cast) together into one else
block is not the best design, and perhaps I should check for both separately (perhaps I should use the more traditional do/try/catch
), but I would like to better grasp the details of this complex construct.
Upvotes: 2
Views: 61
Reputation: 32833
You need to wrap the try
call into parentheses:
let results = (try? managedContext.executeFetchRequest(fetchRequest)) as? [MyManagedObjectClass]
otherwise try?
will apply to the whole expression, generating an optional value that gets assigned to results
.
Upvotes: 3