50

I try to use the error handling modeling in Swift2.

do {
    try NSFileManager.defaultManager().removeItemAtPath("path")
} catch {
    // ...
} finally {
    // compiler error.
}

But it seems that there is no finally keyword out there.How can I achieve try-catch-finally pattern in Swift.Any help is welcome.

tounaobun
  • 14,570
  • 9
  • 53
  • 75
  • 2
    it's **defer** - one of the most important things in all of Swift – Fattie Dec 18 '16 at 16:19
  • 1
    Except sadly, nobody seems to realize that the pattern people will have will also need to run code that might throw at the end yet defer has no capacity for this. What then? – uchuugaka Sep 16 '20 at 04:35

5 Answers5

43

If you are thinking about the SWIFT 2.0 error handling to be the same thing as exception you are missunderstanding.
This is not exception, this is an error that conforms to a protocol called ErrorType.
The purpose of the block is to intercept the error thrown by a throwing function or method.
Basically there is no finally, what you can do is wrap your code in a defer block, this is guaranteed to be execute and the end of the scope.
Here a sample from SWIFT 2 programming guide

func processFile(filename: String) throws {
    if exists(filename) {
        let file = open(filename)
        defer {
            close(file)
        }
        while let line = try file.readline() {
            /* Work with the file. */
        }
        // close(file) is called here, at the end of the scope.
    }
}

You use a defer statement to execute a set of statements just before code execution leaves the current block of code. This lets you do any necessary cleanup that should be performed regardless of whether an error occurred. Examples include closing any open file descriptors and freeing any manually allocated memory.

Andrea
  • 26,120
  • 10
  • 85
  • 131
19

defer in Swift 2.0 is like a finally, that means swift ensures you to execute that defer code at the end of current function scope. Here are the some points that i need to know:

  1. No matter even guard will returns
  2. we can write multiple defer scopes

Here is the example and output that demonstrates multiple defers:

func myMethod()  {
    print("Message one")
    print("Message two")
    print("Message three")
    defer {
        print("defered block 3")
    }
    defer {
        print("defered block 2")
    }
    defer {
        print("defered block 1")
    }
    print("Message four")
    print("Message five")

}

Output:

Message one
Message two
Message three
Message four
Message five
defered block 1
defered block 2
defered block 3
Peter Schorn
  • 916
  • 3
  • 10
  • 20
Narendra G
  • 491
  • 4
  • 9
6

What you are looking for is called defer. It defines a block of code that is not executed until execution is just about to leave the current scope, but it is always executed.

func processFile(filename: String) throws {
    if exists(filename) {
        let file = open(filename)
        defer {
            close(file)
        }
        while let line = try file.readline() {
            /* Work with the file. */
        }
        // close(file) is called here, at the end of the scope.
    }
}

For more details on defer have a look at the Apple Swift documentation, especially section "Specifying Clean-up Actions".

miho
  • 11,765
  • 7
  • 42
  • 85
5

read this : The defer keyword in Swift 2: try/finally done right

for example :

print("Step 1")

do {
    defer { print("Step 2") }
    print("Step 3")
    print("Step 4")
}

print("Step 5")

Output :

Step 1
Step 3
Step 4
Step 2
Step 5
aldo
  • 2,927
  • 21
  • 36
Arash Jamshidi
  • 151
  • 3
  • 6
3

Swift 2 introduces its own take on this requirement using the defer keyword

defer { 
    print("Do clean up here") 
}

finally = defer in Swift 2.

Article for defer keyword

Ashish Kakkad
  • 23,586
  • 12
  • 103
  • 136
  • 12
    "finally = defer" - Not exactly. In a try/catch/finally in languages such as C# or Java, the finally block will be executed regardless of whether there is an exception. This behavior offers the benefit of being able to put code in a finally block that will be executed no matter what. In swift, defer only executes after the current scope, and a catch block would be in a different scope. So it's not quite the same thing as "finally". – dcp Oct 31 '17 at 20:04