Swift Tip: Wrapper Functions
For this year's update to Advanced Swift, we're adding the option for a video bundle (just like we did for App Architecture). One of the videos in the bundle shows how we wrap Cairo, a library for drawing vector graphics.
In our wrapper, we need to do the following:
let surface = try SVGSurface(size: CGSize(width: 800, height: 600))
let context = try Context(surface)
context.drawSomething()
surface.finish()
print(surface.data)
Before we can access the data
of the context, we should call surface.finish()
. And after we call surface.finish()
, we really shouldn't be drawing using context
anymore. Instead of putting this into the documentation, we can also provide a different API that prevents us from making this mistake:
func svg(size: CGSize, _ draw: (Context) -> ()) throws -> Data {
let surface = try SVGSurface(size: size)
let context = try Context(surface)
draw(context)
surface.finish()
return surface.data
}
Now when we want to create an SVG, we call the function with our drawing code:
let data = try svg(CGSize(width: 800, height: 600)) { context in
context.drawSomething()
}
In the sample above, we can't access the surface directly, and we can't forget to call finish()
-- this is taken care of by the wrapper.
We can use the same technique in many places. For example, in Core Graphics (which happens to be similar to Cairo), there's an API that saves the graphic state of a CGContext
, and another one that restores it. Calls to these APIs should be balanced. Rather than calling them directly, again we can write a wrapper function that balances the calls for us:
extension CGContext {
func withLocalGraphicsState(_ draw: () -> ()) {
saveGState()
draw()
restoreGState()
}
}
You can use similar APIs whenever you're dealing with resources that need balanced calls: opening and closing a file, locking and unlocking a shared resource, or pushing and popping some state. We use this pattern throughout our projects. It's much nicer to move these possible points of failure out of our domain specific code, and into helper code that we can test and verify once.
The video bundle will be released shortly, alongside the new edition of Advanced Swift. If you already own the Ebook, the edition update will be free. The videos will be optional, as a paid upgrade. Watch our Twitter for an announcement!