Function throws AND returns optional.. possible to conditionally unwrap in one line?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP


Function throws AND returns optional.. possible to conditionally unwrap in one line?



I am using an SQLite library in which queries return optional values as well as can throw errors. I would like to conditionally unwrap the value, or receive nil if it returns an error. I'm not totally sure how to word this, this code will explain, this is what it looks like:


func getSomething() throws -> Value? {
//example function from library, returns optional or throws errors
}


func myFunctionToGetSpecificDate() -> Date? {
if let specificValue = db!.getSomething() {
let returnedValue = specificValue!
// it says I need to force unwrap specificValue,
// shouldn't it be unwrapped already?

let specificDate = Date.init(timeIntervalSinceReferenceDate: TimeInterval(returnedValue))
return time
} else {
return nil
}

}



Is there a way to avoid having to force unwrap there? Prior to updating to Swift3, I wasn't forced to force unwrap here.



The following is the actual code. Just trying to get the latest timestamp from all entries:


func getLastDateWithData() -> Date? {
if let max = try? db!.scalar(eventTable.select(timestamp.max)){

let time = Date.init(timeIntervalSinceReferenceDate: TimeInterval(max!))

// will max ever be nil here? I don't want to force unwrap!
return time

} else {
return nil
}
}




2 Answers
2



If a function throws and returns an optional


func getSomething() throws -> Value? { ... }



then try? getSomething() returns a "double optional" of the
type Value?? and you have to unwrap twice:


try? getSomething()


Value??


if let optval = try? getSomething(), let val = optval {

}



Here the first binding let optval = ... succeeds if the function did
not throw, and the second binding let val = optval succeeds
if the return value is not nil.


let optval = ...


let val = optval


nil



This can be shortened with case let pattern matching to


case let


if case let val?? = try? getSomething() {

}



where val?? is a shortcut for .some(.some(val)).


val??


.some(.some(val))





Exactly what I was looking for. I haven't seen if case let before, I will have to read about it. Also what do you mean by .some(.some(val)).
– twiz_
Sep 25 '16 at 20:24





@twiz_: Optional is an enumeration with cases .none and .some(wrapped). .some(.some(val)) is a nested optional value, which is not nil, and the unwrapped value is also not nil. Here is another example of using nested optionals stackoverflow.com/questions/27225232/….
– Martin R
Sep 25 '16 at 20:34




.none


.some(wrapped)


.some(.some(val))





Tricky, because if you are only interested in the success of the call, and not the returned data, you may easily be confused if the call returns nil to indicate failure.
– Mike Taverne
Mar 6 at 3:47



I like Martin's answer but wanted to show another option:


if let value = (try? getSomething()) ?? nil {

}



This has the advantage of working outside of if, guard, or switch statements. The type specifier Any? isn't necessary but just included to show that it returns an optional:


if


guard


switch


Any?


let value: Any? = (try? getSomething()) ?? nil






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Arduino Mega cannot recieve any sketches, stk500_recv() programmer is not responding

Visual Studio Code: How to configure includePath for better IntelliSense results

C++ virtual function: Base class function is called instead of derived