Introducing Sourcery Pro

Today I’m happy to announce a new mac app that extends Xcode features.

This is an effort of over 1000 hours, so if there was ever time to show your support for all the open source work I’ve done, it’s now.

Read more

The Decade in Review

Lately, I’ve spent a significant amount of time thinking about my career: what I’ve done so far and what might lie ahead for me.

To gain some perspective, I’ve decided to journal some of the things I’ve done over the last decade, and to share that with you.

So below you will find some of my projects for the Cocoa community, as well as the highlights of commercial work I enjoyed and can talk about (NDA’s).

Improve build times by extracting 3rd party tooling to processing script.

A lot has been written about improving Swift compile times, but the compiler and linker are just part of the equation that slows down our development cycle.

Most projects leverage great 3rd party tools like SwiftLint, Sourcery, SwiftGen, SwiftFormat and many more. Leveraging those tools is the right thing to do but we have to be aware that all of those tools come with some time delay for our build -> run development cycle.

We often set those tools to run as build-phases which means they run each time you attempt a build but none of those tools need to be run each time we build.

Even tools that generate code we need for our projects like Sourcery or SwiftGen don’t need to be re-run unless we made changes in very specific parts of the application.

As an example New York Times main application leverages a lot of 3rd party and internal tooling, the total time all the tools take is 6s on my (powerful) machine.

Only 6 seconds or as much as 6 seconds? Let’s put this into context:

  • I build a project between 200-400 times on an average workday.
  • Let’s assume 90% of the time we don’t need to run those tools with each build.
  • We have 30 iOS developers working on the main app

Lower limit: 200 * 6s * 30 * 90* => 9 hours wasted per day

We are wasting 45 hours per week, if we can improve that it’s almost like hiring a new full-time developer, except it’s free.

Let’s look at how we can improve this with a process change a dash of bash shell programming.

Adding support for versioning and migration to your Codable models.

Codable is a great protocol for automating simple model persistence, but it lacks support for any kind of versioning or migrating the data from older versions.

You can, of course, implement custom Codable adherence and throw in a bunch of if statements and manual decoding to achieve this goal, but isn’t that kind of killing the main selling point of Codable?

Let’s look at an idea that adds Versoning yet still leverages derived Codable.

Straighforward Data Snapshots

If your app has a lot of content, chances are that by the time you get a chance to work on a bug report, the data that the bug appeared on will be long gone.

Here are some tidbits on how I created a simple solution for that problem at The New York Times, it’s based on a simple idea.

Finding exact difference between 2 instances

Have you ever written tests? Usually, they use equality asserts, e.g. XCTAssertEqual, what happens if the object isn’t equal? Xcode throws a wall of text at you:

This forces you to manually scan the text and try to figure out exactly whats wrong, what if instead you could just learn which property is different?

How to find retain cycles and memory leaks sooner

LifetimeTracker can surface retain cycle / memory issues right as you develop your application, and it will surface them to you immediately, so you can find them with more ease.

Instruments and Memory Graph Debugger are great, but too many times developers forget to check for issues as they close the feature implementation.

If you use those tools sporadicaly many of the issues they surface will require you to investigate the cause, and cost you a lot of time in the process.

Metaprogramming in Swift talk

I’ve recently spoke at CraftConf about metaprogramming in Swift using my Sourcery

You can watch the talk online:

Using protocol compositon for dependency injection

I like using composition and dependency injection, but when you need to inject each entity with multiple dependencies, it can get cumbersome fast.

As the project grows and you need to inject more dependencies into your objects, you will end up having to refactor your methods a lot of times, as we all know Xcode doesn’t help with that.

There is a more manageable way.

Stop weak-strong dance

Closures in Swift are extremely useful, they are interchangeable with functions and that creates a lot of opportunities for useful use-cases. One thing we have to be careful when using them is to avoid retain cycles.

We have to do it so often that it begs the question:

Can we improve the call-site API?