My name is Victor Sukochev and I’m an iOS developer at Exyte. Recently we open sourced Macaw — a library for drawing and animating vector graphics. In this article I’d like to share my thoughts about Macaw’s advantages over native API.

There is often a necessity to create custom UI controls and repeat the same CoreGraphics routines to achieve even simplest effects:

Inherit from UIView in order to override drawRect method

Use outdated drawing API

Let’s try to build the following custom control and use it as an example:

Custom control

We decided to get rid of such routine and created Macaw. It can be used to describe a scene in a clear and functional way:

Left: Core Graphics, Right: Macaw

As you can see, our scene is described as a model which can be reused and modified. You can build complex hierarchies with relative characteristics (e.g. position, opacity) by using the Group node type:

I don’t even want to think about maintaining such a hierarchy using pure CoreGraphics. To use the power of Macaw you only need to inherit your control view class from MacawView or use MacawView as a container and let the magic begin. An added benefit is that any change to the scene’s properties will automatically trigger a content update for the view.

There is one more thing required to produce nice visual effects — animation. In raw CoreGraphics API there are basically two ways of doing this:

CAShapeLayer with CABasicAnimation combination. It’s easy, but code still looks outdated:

Use CADisplayLink callback for manual UIView content redrawing. But as a developer I don’t want to go so far for a simple visual effect.

With Macaw an animation like this can be achieved with a simpler approach:

Left: Core Graphics, Right: Macaw

That’s it. All routines are now hidden allowing you to focus on the effect logic. Of course there are more options and mechanisms at your disposal. This is one of my favorite animation combination and sequencing:

Is there any overhead in comparison with CoreGraphics? Under the hood Macaw uses CAKeyframeAnimation and needs to calculate key frames before animation. Other than that it uses the same Core Graphics calls.

Ok, what about animation of content? Is there any way to animate the state of the model objects or replace an entire model tree with animation? Unfortunately there is no way to optimize this process, so the only solution is to manually redraw the content of a layer. Good news — Macaw has a really beautiful API for that.

Let’s refactor our code to make generating a model tree easier:

Now we can implement content animation by replacing the model subtree content every frame:

Content animation

Even with a complex scene only the subtree area will be redrawn via animation.

We can achieve the same performance with more readable and supportable code by using Macaw. There is still functionality left to cover, but I hope this sneak peek will interest you enough to give Macaw a try in your projects. We are continuously improving it and all suggestions and contributions are welcome.