How to Use Hot Module Reloading in Swift

Hot Module Reloading can save you hours of development each day. It works by only compiling parts of your application that have changed instead of having to recompile the entire application each time something changes.

Posted By Adam Bulmer In Swift,XCode

As a Web Engineer, I have been taking Hot Module Reloading for granted. It's something I don't even think about anymore. It's just part of my development workflow because most web frameworks support Hot Module Reloading by default.

Now in 2022 Hot Module Reloading is coming to Swift and it's really easy to set up.

To enable Hot Module Reloading requires the use of InjectionForXcode and a micro-library called Inject.

Inject is a library created by Krzysztof Zabłocki and is universal across UIKit, AppKit and SwiftUI.

Install

  1. Inject is available as an SPM dependency. https://github.com/krzysztofzablocki/Inject.git
  2. Add -Xlinker -interposable to Other Linker Flags within all targets in your project for Debug configuration.

XCode XLinker Flag

  1. Install the latest version of InjectionForXcode within your /Applications folder.
  2. XCode also needs to be installed within the /Applications folder.
  3. Run InjectionForXcode.
  4. Select Open project.

Usage

Add import Inject to the top of the files you wish to Hot Reload.

At this point, you might be thinking we are modifying production code. The great thing about Inject is that in a production build, the code compiles to NO-OP.

SwiftUI

  1. Call .enableInjection() at the end of your body definition.
  2. Add @ObserveInjection var inject to your view struct
import Inject
import SwiftUI

struct HomeView: View {
	@ObservedObject private var inject = Inject.observer
	var body: some View {
		ContentView()
			.enableInjection()
	}
}

AppKit / UIKit

Inject provides two Host helpers that aid in cleaning up the state between injection phases.

  1. Inject.ViewControllerHost.
  2. Inject.ViewHost.

In both cases, we don’t modify the class we want to be injecting but instead, want to modify the parent class.

let body = Inject.ViewHost(
  YourInjectedViewController(your: arguments)
)

Conclusion

I can't believe it's 2022 and we are only now getting a good developer experience for Hot Module Reloading on Apple Platforms.

Subscribe To The Newsletter

If you want to create your first native app or have just begun your native app development journey, be sure to sign up to the newsletter. No Spam