Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between a defer statement and a statement right just before return?

Tags:

What's the difference between this:

_ = navigationController?.popViewController(animated: true)  defer {     let rootVC = navigationController?.topViewController as? RootViewVC     rootVC?.openLink(url: url) } return 

and this:

_ = navigationController?.popViewController(animated: true)  let rootVC = navigationController?.topViewController as? RootViewVC rootVC?.openLink(url: url) return 

Apple's swift guideline says: “You use a defer statement to execute a set of statements just before code execution leaves the current block of code. ”,but still I don't quite get it.

like image 968
Li Fumin Avatar asked Feb 28 '17 15:02

Li Fumin


People also ask

Is defer called before return?

Like the Defer Completion example, a defer statement can be used ensure a completion block is called with appropriate values before a function returns. Defer Logic. Like the Defer Logic example, a defer statement can be used to ensure key logic like closing a file executes before a function returns.

What is defer statement?

A defer statement defers the execution of a function until the surrounding function returns. The deferred call's arguments are evaluated immediately, but the function call is not executed until the surrounding function returns.

What does defer mean Swift?

A defer statement is used for executing code just before transferring program control outside of the scope that the defer statement appears in. A defer statement has the following form: defer { statements. }

What does the defer block do?

The most common use case for the Swift defer statement is to unlock a lock. defer can ensure this state is updated even if the code has multiple paths. This removes any worry about forgetting to unlock, which could result in a memory leak or a deadlock.


1 Answers

What's the difference between a defer statement and a statement right just before return?

All the difference in the world. The defer statement is executed after the return! This allows you to accomplish things that can be accomplished in no other way.

For example, you can return a value and then change the value. Apple makes use of this trick quite regularly; here, for example, is code from the Sequence documentation showing how to write a custom Sequence:

struct Countdown: Sequence, IteratorProtocol {     var count: Int      mutating func next() -> Int? {         if count == 0 {             return nil         } else {             defer { count -= 1 }             return count         }     } } 

If you wrote that as

            count -= 1             return count 

... it would break; we don't want to decrement count and then return it, we want to return count and then decrement it.

Also, as has been already pointed out, the defer statement is executed no matter how you exit. And it works no matter you exit the current scope, which might not involve return at all; defer works for a function body, a while block, an if construct, a do block, and so on. A single return is not the only way to exit such a scope! There might be more than one return in your method, and/or you might throw an error, and/or you might have a break, etc. etc., or you might just reach the last line of the scope naturally; the defer is executed in every possible case. Writing the same code "by hand", so as to cover every possible exit, can be very error-prone.

like image 199
matt Avatar answered Sep 28 '22 04:09

matt