wnagrodzki / iOSProgrammingGuidelines

2 stars 0 forks source link

Avoid force unwrapping #3

Closed wnagrodzki closed 6 years ago

wnagrodzki commented 6 years ago

Use guard and fatalError() instead of force unwrapping to clarify your intent.

guard let value = optionalValue else { fatalError("reason why value must be present") }

This is to avoid situations in which reason for force unwrapping is undocumented.

pwetrifork commented 6 years ago

I saw a suggestion somewhere to define an operator analogous to ?? for this, perhaps something like !? where the right operand is a string to be passed to fatalError() could be added to our helper frameworks.

wnagrodzki commented 6 years ago

@pwetrifork Unwrap or Die operator

wnagrodzki commented 6 years ago

The following operator makes it possible to write a shorthand form of the guard statement listed in the first comment.

let user = optionalUser !! "User must be present"
infix operator !!: NilCoalescingPrecedence

extension Optional {
    /// Performs a forced unwrap operation, returning
    /// the wrapped value of an `Optional` instance
    /// or performing a `fatalError` with the string
    /// on the rhs of the operator.
    ///
    /// Forced unwrapping unwraps the left-hand side
    /// if it has a value or errors if it does not.
    /// The result of a successful operation will
    /// be the same type as the wrapped value of its
    /// left-hand side argument.
    ///
    /// This operator uses short-circuit evaluation:
    /// The `optional` lhs is checked first, and the
    /// `fatalError` is called only if the left hand
    /// side is nil. For example:
    ///
    ///    guard !lastItem.isEmpty else { return }
    ///    let lastItem = array.last !! "Array guaranteed to be non-empty because..."
    ///
    ///    let willFail = [].last !! "Array should have been guaranteed to be non-empty because..."
    ///
    ///
    /// In this example, `lastItem` is assigned the last value
    /// in `array` because the array is guaranteed to be non-empty.
    /// `willFail` is never assigned as the last item in an empty array is nil.
    /// - Parameters:
    ///   - optional: An optional value.
    ///   - message: A message to emit via `fatalError` after
    ///     failing to unwrap the optional.
    public static func !!(optional: Optional, errorMessage: @autoclosure () -> String) -> Wrapped {
        if let value = optional { return value }
        fatalError(errorMessage())
    }
}

Source Swift forum thread The proposal has been rejected