Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defer block is not executed

Tags:

swift

deferred

I have the following swift code executing in playground:

func A() {
    print ("Hello")
    guard 1 == 2 else {
        return
    }
    defer {
        print ("World")
    }
}
  
A()

I expected to see

Hello
World

Instead only the Hello is printed. Why is this? What am I missing?

Here is a better example:

enum MyError: ErrorType {
    case TriggerDefer
}

func throwsMyError() throws {
    let myzero = Int(arc4random_uniform(1))
    
    guard myzero > 1 else {
        throw MyError.TriggerDefer
    }
}

func A() throws {
    try throwsMyError()
    
    defer {
        print ("Hello World")
    }
}

As per the answers and comments, the correct way to do this (with an example) is

enum MyError: ErrorType {
    case TriggerDefer
}

func throwsMyError() throws {
    let myzero = Int(arc4random_uniform(1))

    print("Hello")

    guard myzero > 1 else {
        throw MyError.TriggerDefer
    }
}

func A() throws {        
    defer {
        print ("World")
    }
     
    try throwsMyError()
}

The output will now be

Hello
World
like image 814
smac89 Avatar asked Mar 23 '16 03:03

smac89


People also ask

What does the defer block do?

The defer statement will keep your iOS application code running smoothly, even if a team member updates a method or adds a conditional statement. defer executes no matter how we exit and future proofs projects from changes that may alter the scope flow, reducing the possibility of an error.

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.


2 Answers

What you're missing is that deferis not magic. It is executable code, just like any other code. If the path of execution never encounters it, there is nothing to be deferred. This is why it should always be dead first in the block on whose exit it is to be executed — so that we guarantee that it is encountered.

like image 191
matt Avatar answered Sep 30 '22 14:09

matt


Put the defer block before the scope is exited:

func A() {
    print ("Hello")
    defer {
        print ("World")
    }
    guard 1 == 2 else {
        return
    }
}

A()
like image 39
Tim Vermeulen Avatar answered Sep 30 '22 15:09

Tim Vermeulen