How to exit a function scope from inner function using Swift?
This is basically what Swift's error handling does:
func outer() throws
{
try inner()
print("Unreachable")
}
struct DoNotContinue : Error {}
func inner() throws
{
throw DoNotContinue()
}
do { try outer() }
catch _ { print("Skipped the unreachable") }
Note, of course, that the caller still has control over this: it could catch the thrown error itself instead of just exiting.
problem with this approach is that it can clutter your code
There's a much more serious problem with allowing callees to directly exit their callers, and that is that the flow of control very quickly becomes incomprehensible. Imagine that you have a couple of layers of this. Reading the top-level function, you no longer have any clear idea what can happen. You must yourself recurse into every callee's callee to make sure that the original code will continue on its course.
How to exit GUARD outside and inside a function - Swift
If the condition in your guard
statement is not met, the else branch has to exit the current scope. return
can only be used inside functions, as the error message shows, but return
is not the only way to exit scope.
You can use throw
outside functions as well and if the guard
statement is in a loop, you can also use break
or continue
.
return
valid in functions:
func testGuard(){
guard 2+2 == 4 else {
print("The universe makes no sense")
return // this is mandatory!
}
print("We can continue with our daily lives")
}
throw
valid outside of function as well:
guard 2+2 == 4 else { throw NSError() }
break
valid in loops:
for i in 1..<5 {
guard i < 5 else {
break
}
}
continue
valid in loops:
for someObject in someArray {
guard let someProperty = someObject.someOptionalProperty else {
continue
}
}
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
andthrow
both exit the function/methodcontinue
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 inif
scopes.
Additionally, you may exit the scope by calling a function that returns Never
, such as fatalError
.
Swift - Exit outer function from closure
Swift does not have non-local returns from closures. In other words, there is no direct way to return out of multiple levels. This only works with inlined functions in Kotlin, but Swift does not have this distinction.
There are other collection methods which stop once an element is found, for example index(where:)
.
func lookForLetter(letter: String, letters: [String]) {
guard let _ = letters.index(where: { (l) in
if l == letter {
print("Found");
return true
}
print(l)
return false
}) else {
print("Completed")
return
}
}
Swift - Exit function with background thread inside
As far as I know if you want to stop execution of for loop which is running on background thread, then you have to stop it from background thread itself which you are trying to stop from main thread block of code. try something line below :
func doSomething() {
var continueForLoop = true
DispatchQueue.global(qos: .userInteractive).async {
for ... {
if ... && continueForLoop{
...
DispatchQueue.main.sync {
//Update UI
...
if ... {
// Show UIAlert
//Exit function
continueForLoop = false
}
}
}else{
break;
}
}
}
}
P.S. to understand multithreading in iOS go thought this link : iOS Concurrency Note: try to understand the multithreading part only as code contains old swift syntaxes.
Function inside Function retain cycle
Just assign your closure to a local variable. At that point, extracting out dismiss
is pointless, so just inline it:
private func setupDismissCallbacks() {
let dismissCallback: () -> Void = { [weak self] in
guard let self = self else { return }
self.videoExporter?.cancel()
self.rootViewController.dismiss(animated: true, completion: nil)
self.delegate?.childCoordinatorDidFinish(self)
}
saveModalViewController.onButtonDismiss = dismissCallback
saveModalViewController.onDimmedAreaDismiss = dismissCallback
}
Related Topics
I Opened My App in Xcode 10 and Now I Have Errors in 9.4.1: Sdkapplicationdelegate (Facebookcore)
Weird Toolbar with Nested Conditionals Behavior
Parse Migration Error to Mlabs and Heroku
Swift Error "Static Member Cannot Be Used on Instance of Type"
Avaudiopcmbuffer Built Programmatically, Not Playing Back in Stereo
How to Detect Touches on UIimageview of UItableviewcell in Swift
Leaving Equal Width Gap Spacing Before and Between Menu Buttons
Swiftui Previews - Unexpected Data
Swiftui Multiple Animations for Same Element
Exc Bad Access While Creating a New Characterset
Why Do I Have to Unwrap a Weak Self
How to Prevent SQL Injections with User-Search-Terms in Vapor 4 (Fluent 4)
How to Cache Cells and Also Reuse Cells in a Collectionview That Has Avplayers Embedded in Each Cell
Does Realm Support Computed Property in Swift
How to Save Re-Ordered Tableview Cells to Core Data
Audiounit Callback and Synchronization: How to Ensure Thread Safety with Gcd