Super Mario World Review link

Matt Greer wrote a highly detailed review of my favorite 2D Mario game, Super Mario World.

Welcome!

It also features some super slick videos of gameplay footage as well as a basic Mario music player.

The review was written as a web app using ClojureScript and Om and its code can be found on GitHub, together with the sources for the program he wrote to generate the videos.

CocoaPods Keys link

Orta released a clever new CocoaPods plug-in to manage keys, application secrets and the like. Pretty much everything you don’t want to check into your repository.

After you install the plug-in, storing the keys in the OS X Keychain and accessing them in your code becomes dead simple:

You can save keys on a per-project basis by running the command:

$ pod keys set KEY VALUE

After the next pod install or pod update keys will add a new Objective-C class to your Pods xcworkspace.

#import "ORAppDelegate.h"
#import <CocoaPods-Keys/MyApplicationKeys.h>
#import <ARAnalytics/ARAnalytics.h>

@implementation ORAppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    MyApplicationKeys *keys = [[MyApplicationKeys alloc] init];
    [ARAnalytics setupWithAnalytics:@{
        ARGoogleAnalyticsID : keys.analyticsToken;
    }];
}

@end

I think this is a great example of what can be built on top of the CocoaPods infrastructure. That being said, I assume that someone will write a similar but independent script soon.

Note that it depends on the upcoming CocoaPods 0.34.

Scott Goodson - Asynchronous UI link

Scott Goodson shared some more insights into building Paper at NSLondon:

(If you’re not being served the flash embed, skip to 13:00, silly Livesteam…)

How to build a nice Hamburger Button transition in Swift

Hamburger buttons may have become somewhat of a cliché in interface design lately, but when I came across a particularly nice transition of a hamburger button on dribbble, I had to try and recreate it in code.

Here’s the original shot by the CreativeDash team:

You’ll notice how the top and bottom strokes of the hamburger form a X, while the middle one morphs into an outline. I knew this effect could be recreated using CAShapeLayer, but first I had to create a CGPath for each of the three strokes.

The short, straight strokes can be figured out manually:

let shortStroke: CGPath = {
    let path = CGPathCreateMutable()
    CGPathMoveToPoint(path, nil, 2, 2)
    CGPathAddLineToPoint(path, nil, 28, 2)

    return path
}()

For the middle stroke however, I created a path in Sketch that starts from the middle and seamlessly transitions into the outline.

I then exported this path as an SVG file and imported it into the old PaintCode 1, which converted the file into a code snippet that created a UIBezierPath. I then rewrote said piece of code into the following instructions that create the desired CGPath object:

let outline: CGPath = {
    let path = CGPathCreateMutable()
    CGPathMoveToPoint(path, nil, 10, 27)
    CGPathAddCurveToPoint(path, nil, 12.00, 27.00, 28.02, 27.00, 40, 27)
    CGPathAddCurveToPoint(path, nil, 55.92, 27.00, 50.47,  2.00, 27,  2)
    CGPathAddCurveToPoint(path, nil, 13.16,  2.00,  2.00, 13.16,  2, 27)
    CGPathAddCurveToPoint(path, nil,  2.00, 40.84, 13.16, 52.00, 27, 52)
    CGPathAddCurveToPoint(path, nil, 40.84, 52.00, 52.00, 40.84, 52, 27)
    CGPathAddCurveToPoint(path, nil, 52.00, 13.16, 42.39,  2.00, 27,  2)
    CGPathAddCurveToPoint(path, nil, 13.16,  2.00,  2.00, 13.16,  2, 27)

    return path
}()

There probably is a library that allows you to load CGPaths straight from SVG files, but for a short path like this one, having it in code is not a big deal.

In my UIButton subclass, I added three CAShapeLayer properties and set the their paths accordingly:

self.top.path = shortStroke
self.middle.path = outline
self.bottom.path = shortStroke

Then I styled all three of them like so:

layer.fillColor = nil
layer.strokeColor = UIColor.whiteColor().CGColor
layer.lineWidth = 4
layer.miterLimit = 4
layer.lineCap = kCALineCapRound
layer.masksToBounds = true

In order to calculate their bounds correctly, I needed take the size of the stroke into account. Thankfully, CGPathCreateCopyByStrokingPath will create a path that follows the outlines of the original stroke, therefore its bounding box will then fully contain the contents of the CAShapeLayer:

let boundingPath = CGPathCreateCopyByStrokingPath(layer.path, nil, 4, kCGLineCapRound, kCGLineJoinMiter, 4)

layer.bounds = CGPathGetPathBoundingBox(boundingPath)

Since the outer strokes will later rotate around their right-most point, I had to set their anchorPoint accordingly when layouting their layers:

self.top.anchorPoint = CGPointMake(28.0 / 30.0, 0.5)
self.top.position = CGPointMake(40, 18)

self.middle.position = CGPointMake(27, 27)
self.middle.strokeStart = hamburgerStrokeStart
self.middle.strokeEnd = hamburgerStrokeEnd

self.bottom.anchorPoint = CGPointMake(28.0 / 30.0, 0.5)
self.bottom.position = CGPointMake(40, 36)

Now, when the button changes state, it should animate the three strokes to their new positions. Once again, the two outer strokes are easy. For the top stroke, I first moved it inward by 4 points to keep in centered, then rotated it by negative 45 degrees to form one half of the X:

var transform = CATransform3DIdentity
transform = CATransform3DTranslate(transform, -4, 0, 0)
transform = CATransform3DRotate(transform, -M_PI_4, 0, 0, 1)

let animation = CABasicAnimation(keyPath: "transform")
animation.fromValue = NSValue(CATransform3D: CATransform3DIdentity)
animation.toValue = NSValue(CATransform3D: transform)
animation.timingFunction = CAMediaTimingFunction(controlPoints: 0.25, -0.8, 0.75, 1.85)
animation.beginTime = CACurrentMediaTime() + 0.25

self.top.addAnimation(animation, forKey: "transform")
self.top.transform = transform

(The bottom stroke is left as an exercise to the reader.)

Again, the middle stroke is a little trickier. In order to achieve the desired effect, I needed to animate the CAShapeLayer’s strokeStart and strokeEnd properties separately.

First I had to figure out the correct values for the two properties in the two states. Note that the even in its hamburger state, the stroke does not start at 0. By having the path extend slightly beyond the left edge of the outer strokes, we can achieve a nice anticipation effect when applying the timing function later:

let menuStrokeStart: CGFloat = 0.325
let menuStrokeEnd: CGFloat = 0.9

let hamburgerStrokeStart: CGFloat = 0.028
let hamburgerStrokeEnd: CGFloat = 0.111

Now we only need to create the animations and add them to the layer:

let strokeStart = CABasicAnimation(keyPath: "strokeStart")
strokeStart.fromValue = hamburgerStrokeStart
strokeStart.toValue = menuStrokeStart
strokeStart.duration = 0.5
strokeStart.timingFunction = CAMediaTimingFunction(controlPoints: 0.25, -0.4, 0.5, 1)

self.middle.addAnimation(strokeStart, forKey: "strokeStart")
self.middle.strokeStart = menuStrokeStart

let strokeEnd = CABasicAnimation(keyPath: "strokeEnd")
strokeEnd.fromValue = hamburgerStrokeEnd
strokeEnd.toValue = menuStrokeEnd
strokeEnd.duration = 0.6
strokeEnd.timingFunction = CAMediaTimingFunction(controlPoints: 0.25, -0.4, 0.5, 1)

self.middle.addAnimation(strokeEnd, forKey: "strokeEnd")
self.middle.strokeEnd = menuStrokeEnd

Putting everything together, the result looks something like this:

I’m pretty happy with how it turned out. If you are too, you can find the code on GitHub and follow me on Twitter.

Cartography link

If you follow the Apple developer community, you’ve probably heard of Swift by now, Apple’s new programming language for iOS and OS X apps.

Some of Swift’s features, such as operator overloading and implicit closures allow us to create powerful yet typesafe DSLs. For example, I recently released my first Swift open source library, Cartography, that makes use of both of these features.

Inspired by the awesome FLKAutoLayout, Cartography allows you to create Auto Layout constraints in a declarative fashion.

While NSLayoutConstraint supports what they call a visual format string, its syntax is not very intuitive. Additionally, since it is, well, a string, the compiler can’t assist you with validating your expression either. Compare this example I adapted from Apple’s documentation

NSArray *constraint = [NSLayoutConstraint
    constraintsWithVisualFormat:@"[view1]-20-[view2]"
    options:0
    metrics:nil
    views:NSDictionaryOfVariableBindings(view1, view2)];

[view2 addConstraint:constraint];

with the equivalent Cartography code:

layout(view1, view2) { view1, view2 in
    view2.left == view1.right + 20
}

Fixed aspect ratios can’t even be expressed using the visual format string, you would have to use the lower level +constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:​. With Cartography, they are concise and readable:

layout(imageView) { imageView in
    imageView.width == 2 * imageView.height
}

I also managed to created new attributed to constraint multiple attributes at the same time:

layout(view) { view in
    view.size   <= view.superview!.size / 2
    view.center == view.superview!.center
}

As usual, you can find Cartography on GitHub.

RACDC 2014

GitHub hosted RACDC 2014 during WWDC two weeks ago, which was a lot of fun. Justin spoke about the Future of ReactiveCocoa and what to expect in RAC 3.0 here:

Also check out Dave Lee’s talk RACify Non-Reactive Code and Jon Sterling’s Modularity à la Taliban as well as the panel discussion.

Swimming (Patrick Ellis Remix) link