Search code examples
swiftswift2guard

Why can’t I use guard when setting AVAudioSession category?


This is a simple Swift 2.0 question, hopefully with a simple answer:

Why does the following code give an error “Ambiguous reference to member setCategory”:

guard AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient) else {
    //
}

Yet this code does not throw that error:

do {
    try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient)
} catch {
     //
}

I don’t intend to take any action if this call doesn’t fail, but I’d still prefer not to use try! – so can I guard this statement? Or, have I misunderstood guard?


Solution

  • From the Control Flow documentation:

    Early exit
    A guard statement, like an if statement, executes statements depending on the Boolean value of an expression. You use a guard statement to require that a condition must be true in order for the code after the guard statement to be executed.

    A typical example is

    guard <someCondition> else { return }
    

    to "early return" from a function if a condition is not met.

    But throwing functions are not Boolean expressions, they must be called in some "try context", as documented in Error Handling:

    Handling Errors
    When a function throws an error, it changes the flow of your program, so it’s important that you can quickly identify places in your code that can throw errors. To identify these places in your code, write the try keyword—or the try? or try! variation—before a piece of code that calls a function, method, or initializer that can throw an error.

    So this are completely different things. The guard statement cannot be used with throwing functions.

    If you don't care about success or failure of a throwing function, use try? and ignore the result as in An elegant way to ignore any errors thrown by a method. In your case:

    _ = try? AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient)