Is there a way to embed an assertionFailure into '??' expression?

91 Views Asked by At
TimeZone(abbreviation: "GMT+1") ?? TimeZone.current

If you want to have a non optional and assert before TimeZone.current fallback is used after ?? what syntax would I use in swift?

something like this

TimeZone(abbreviation: "GMT+1") ?? (assertionFailure("what weird runtime have you've got????"), TimeZone.current)

(which obviously does not compile)

2

There are 2 best solutions below

0
Ivan Stebletsov On BEST ANSWER

Try to write extension for Optional where you can handle your case, for example:

extension Optional {
    func rescue(
        _ assertion: String, 
        _ fallback: Wrapped
    ) -> Wrapped {
        guard case let .some(value) = self else {
            assertionFailure(assertion)
            return fallback
        }
        
        return value
    }
}
TimeZone(abbreviation: "GMT+1").rescue("what weird runtime have you've got????", .current) // GMT+0100
TimeZone(abbreviation: "GMT+1lalala").rescue("what weird runtime have you've got????", .current) // what weird runtime have you've got????
0
JeremyP On

I have a slightly different solution using a generic function.

import Foundation

func fail<T>(_ message: @autoclosure () -> String, fallback: T) -> T
{
    assertionFailure(message())
    return fallback
}

let x = TimeZone(abbreviation: "GMT+1") ?? fail("x is not a valid time zone", fallback: TimeZone.current)

let y = TimeZone(abbreviation: "GMT+1fdsgfds") ?? fail("y is not a valid time zone", fallback: TimeZone.current)
// On evaluating the last statement, aborts with Fatal error: y is not a valid time zone
// in a debug or playground context