Code Generation in Swift

Discover use-cases of code generation and get an overview of the tools you can use to automate it

Maksym Shcheglov
Nov 20, 2019 · 4 min read
Thanks to undraw.co for a great illustration

While working on the iOS project you can find yourself quite frequently writing boilerplate code. This is the code that you prefer not to write by hand and tempt to copy & paste most of the times. It can lead to certain mistakes and even crashes in runtime. In this situation, code generation might be useful. It lets you generate boring and repetitive code and make an application more reliable.

In this post let’s take a look at the use-cases when code generation makes sense and make an overview of the tools we can use to automate it.

Photo by Safar Safarov on Unsplash

Code generation use cases

Code generation is not a new technique and is used already in many Android, Golang, etc. projects. You might be using Sourcery in your project already, that is a popular tool for code generation and metaprogramming in Swift.

First of all, let’s define the most common use cases for code generation:

  • Resource accessors
  • Test mocks
  • Dependency Injection
  • DTO models

It should be mentioned that Swift evolves, we don’t need code generation for certain tasks anymore. This includes automatic synthesis for Codable, Equatable, Hashable and CaseIterable protocols.

Unfortunately there is no an equivalent to Android’s R class in iOS. That’s why access to application resources like assets, localization strings, etc. is evaluated in runtime. This can lead to certain issues when a resource is missing in the application bundle.

Luckily there is a great tool Swiftgen, which allows you to auto-generate Swift code for resources of your projects. With SwiftGen you get type-safe access to the resources and avoid the risk of using non-existing ones. It can generate constants for the next resource types:

  • Asset Catalogs
  • Localization strings
  • IB Storyboards
  • Colors
  • Fonts
  • JSON/YAML/Plist
  • Core data models

SwiftGen uses Stencil templating language to define templates. It comes bundled with some ready-to-use templates and allows to create custom ones. I’d suggest checking the following guide to get an overview of Stencil and become familiar with its syntax.

In static languages like Swift unit testing with mocks is a bit problematic. The reason is that you can’t dynamically create or modify a class behavior in runtime. As an option, you can use OCMock library, but it is limited to NSObject subclasses and doesn’t provide full Swift support. We could use reflection, but it is quite restrained in Swift and is not suitable for creating mocks in runtime. The other options would be creating these test mocks manually by defining a class that conforms to a protocol. But it can result in a significant amount of tedious and repetitive work.

Luckily enough you can use tools to autogenerate mock objects that can be used in your tests:

With the help of those, you can automate writing and maintaining mock implementations, that you’ve done manually.

Dependency Injection is one of the fundamental software development patterns. It represents Inversion of Control technique for supplying dependencies to a class via constructor, public property or setter function.

As your project gets bigger, injecting dependencies and passing them down through several layers of abstractions becomes more time-consuming. This is the reason why you can start using DI framework in your project. Tools like Weaver and Needle are inspired by Dagger and utilize code generation. They take responsibility for generating the necessary boilerplate code to inject dependencies. Eventually you get more confidence by ensuring dependency injection code is compile-time safe: if it compiles, it works.

Quite often when integrating with RESTful APIs you have to define lots of Data transfer objects. It is clear that this approach is inefficient and can lead to bugs in your code.

Luckily you can generate a client-side code if backend uses Swagger and exposes Open API Specification(Swagger Specification) files. There are several options for doing it:

It should be pointed out that both tools use templates for code generation. You can provide a custom one if you are not satisfied with the default syntax.

Apple engineers are using code generation as well. Swift maintainers created a python-based templating tool called GYB, that is an acronym for “Generate Your Boilerplate”. It might be helpful when you have abstractions with a common structure. Instead of maintaining several versions of similar code, you can define a single template and generate the rest of classes/structs/enums.

You can check Codable.swift.gyb template file to get an idea about GYB templates. There is also a nice article about GYB and how to adopt it in your project posted at NSHipster.

Conclusion

Code generation is an effective way to increase your productivity and make your application more robust. You might be familiar with code generation in iOS and tried Sourcery or Swiftgen already. If not, I’d suggest starting with Resource accessors or Test mocks code generation. In this way, you can remove the need to maintain the boilerplate code manually and focus on other important things.

Feel free to follow me on Twitter and ask questions related to this post.

Thanks for reading!

Flawless iOS

🍏 Community around iOS development, mobile design, and…

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store