Defer; defer; defer

Someone was asking about defer, and the order in which they’re added to the stack. It’s pretty easy to create a test set-up like this one so you can play with them yourself.

Here are a few inspirational ways to use defer:

Pair tear-down tasks with setup. For example, if you’re deploying to pre-iOS 10, you might use begin and end for image contexts. Defer is also great for alloc/dealloc, fopen/fclose, etc.

UIGraphicsBeginImageContext(size); defer { UIGraphicsEndImageContext() }

Postdecrement/postincrement. Use defer to return a value before modifying it:

defer { x = x - 1 }; return x // x--

Apply “next state” updates. Use defer in sequence calls, like this example that repeatedly circles through the color wheel:

return sequence(state: hue, next: {
     (state : inout CGFloat) -> Color? in
     defer { state = state + stepAngle }
     ...
     return value }

Leverage group layout. This example draws an array of images into a line. The actual code does a lot of fussy work. Moving defer to the start of the forEach loop helps keep track of the “next step” without searching through the actual layout code.

allImages.forEach { image in
    defer { px += image.size.width + spaceOffset }
    image.draw(at: CGPoint(x: px, y: py))
}

Handy, no?

One Comment

  • Shouldn’t tear-down really be governed by some kind of reference counting, rather than by program block structure?