Swift Error: Guard Body Must Not Fall Through

Swift error: guard body must not fall through

The guard statement needs to have a something to take the flow of the program away from the enclosing scope (e.g. most likely case is return to return from the function). This is required as the condition that guard is guarding will not be valid, so the program flow needs to go elsewhere!

Documentation:

The else clause of a guard statement is required, and must either call
a function marked with the noreturn attribute or transfer program
control outside the guard statement’s enclosing scope using one of the
following statements:

  • return
  • break
  • continue
  • throw

Getting guard body may not fall through error when setting up Google Analytics on iOS Project (in Swift)

guard let function needs to exit the current scope of your gai variable. So you need to modify your code to

guard let gai = GAI.sharedInstance() else {
assert(false, "Google Analytics not configured correctly")
return true//Base on your function return type, it may be returning something else
}

Here is the document:

The else clause of a guard statement is required, and must either call
a function marked with the noreturn attribute or transfer program
control outside the guard statement’s enclosing scope using one of the
following statements:

return break continue throw

Guard statement in Swift has error if using return

The error is saying that your guard statement is within a func() that has an expected return value of some type

For example in the greet() function a String is returned… so the guard statement must return a String value. The type of the value you have to return from your guard statement will depend on the function that contains it.

func greet(person: String, day: String) -> String {
guard person != "Homer" else {
return "Sorry, no Homer's allowed"
}

return "Hello \(person), have a great \(day)"
}

greet(person: "Homer", day: "Monday")

greet(person: "Douglas", day: "Thursday")

If the String "Sorry, no Homer's allowed" isn't returned in the example greet() function you will see the same problem:

broken guard statement

A guard statement simply protects against an unusable state for the function it's enclosed in. So the return statement of a guard is just a form of early return for the function, as such, it must return the same type as the functions definition.

In the greet() function above the definition specifies that a String is returned (-> String) , so the return inside the guard's else block must also return a String.

Swift: Benefit of using a guard-statement?

I don't think that is a very good example of using guard, it is more common to use it with variables that might be nil (aka optional) or functions that might return nil. I suggest you read about the guard statement in the Swift Programming Language book (just scroll down a bit to "Early Exit")

We could make a better example from your code that is lacking some validation

func getEmail(email: String?) -> String? {
guard let input = email, !input.isEmpty else {
return nil
}

return input + "@somewhere.com"
}

Here we use guard to check that the parameter email is not nil by assigning it to a local variable input. If it is nil the function will return nil and otherwise it will check if it is empty and then it will also return.

If it is ok the function will continue and create and return an email address. Note that the function is declared to return an optional string since I think it is much clearer if a function like this returns nil rather than an empty string if it fails.

If the Swift 'guard' statement must exit scope, what is the definition of scope?

It is totally possible to do what you envision, it just happens to not be what that particular code does. return always exits a method, not the local scope. To do what you wish, you can use a label, and break:

func testGuardControlFlow () {

let x = 2
let y = 2

func embededFunc () {

breakLabel:
if y == 2 {

guard x == 1 else {
print("oops, number is not 1")
break breakLabel
}

print ("from in embededFunc")

}

print ("I still want this to print even if x != 1")
}

embededFunc()
print("Great, return still allows this to be printed.")

}

testGuardControlFlow()

To add on to vadian's answer:

guard forces you to exit the scope using a control transfer statement. There are 4 available to you:

  • return and throw both exit the function/method
  • continue can be used within loops (while/for/repeat-while)
  • break can be used in loops (while/for/repeat-while) to exit the immediate scope. Specifying a label to break to will allow you to exit multiple scopes at once (e.g. breaking out of nested loop structure). When using a label, break can also be used in if scopes.

Additionally, you may exit the scope by calling a function that returns Never, such as fatalError.

Using the guard condition in the body of statement

As the error states, you can't use a variable that you bound in the guard statement inside of the guard statement's body. The variable only gets bound in the case where the guard body is not entered. You also aren't differentiating between the cases where your response is nil and where your status code isn't 200.

You should break the statements into two different checks:

guard let httpResponse = response as? NSHTTPURLResponse else {
return NSError(domain: "Error with request", code: 1, userInfo: [NSLocalizedDescriptionKey: "Invalid response: \(response)"])
}

guard httpResponse.statusCode == 200 else {
return NSError(domain: "Error with request", code: 1, userInfo: [NSLocalizedDescriptionKey: "Recieved the following status code: \(httpResponse.statusCode)"])
}

Don't try to minimize the number of lines of code at the expense of readability or correctness.



Related Topics



Leave a reply



Submit