BiteofanApple Archive About Apps Microblog Photos Links
by Brian Schrader

Python-like Context Managers in Swift

Posted on Wed, 25 May 2016 at 03:25 PM

One of the most expressive concepts in Python is the context manager, and their simplest use case is reading and writing files.

with open('path/to/my/file') as f:
    f.write(some_data)

All of the logic that handles opening the file, checking for errors, and closing the file is handled automatically by the with statement. This allows developers to write cleaner, more expressive code without worrying about the nitty gritty details of opening/closing files, and Python allows you to write your own context managers. This makes it easy to clean up any code that needs to execute in a given, safe context.

Enter Swift

Swift doesn't have the concept of a context manager, but they can still be easily implemented using Swift's clean and clear closure syntax.

One of the most helpful use-cases for a context manager in Cocoa is in a custom view's drawRect function. CGContexts can get confusing if you're having to deal with them yourself. If only we had some sort of manager for these contexts.


// First let's define our context manager function.
func drawBlockInSafeContext(block: (context: CGContext?) -> ()) {
    let context = UIGraphicsGetCurrentContext()
    CGContextSaveGState(context)
    block(context: context)
    CGContextRestoreGState(context)
}
class MyView: UIView {
    //...
    func drawRect(rect: CGRect) {
        drawBlockInSafeContext { context in
            // Now we can draw our view 
            // without polluting the root context 
        }
    }
}

Context Managers are one of my favorite features of Python and I'd love to see the concept carried over to Swift. For the record: Omar Abdelhafith has a great tutorial on making more advanced, and more Pythonic Swift Context Managers.

Creative Commons License