How To Be The iOS Team Hero: Add Hot Reloading to Xcode 9

Rob Norback
4 min readOct 12, 2017

--

The first thing I notice is their eyes. They all get a bit bigger. People start to sit up and lean forward. All heads turn away from me, even though I’m the one speaking at the front of the room. They’re all squinting now, trying to make sure they’re seeing the simulator right.

They can’t believe it. Xcode is hot reloading.

Take a look for yourself:

A short demo of hot reloading in Xcode

What is this sorcery?

Good question! This is Injection II, the App. It works with the Xcode simulator and allows you to hot reload your app in less than a second. It works by using the Objective-C runtime to swizzle any code you save on top of the code already running in the simulator.

How do I use it?

If you don’t setup Injection well, it can be nearly useless. So I’ll walk you through 7 steps that’ll have you hot reloading like a pro.

1. Download the App from John Holdsworth’s site. It’s free. He’s awesome.

2. Next run the app on your Mac.

3a. Pull up Xcode and add this code in a new file.

import UIKit

extension UIViewController { //5

#if DEBUG //1
@objc func injected() { //2
for subview in self.view.subviews { //3
subview.removeFromSuperview()
}

viewDidLoad() //4
}
#endif
}
  1. The #if DEBUG is a precompiler macro that will make sure you don’t ship this code with your app (it’s definitely not safe to have this in your app store ).
  2. The the injection app works by running the injected() function. It runs the code inside every time you press Control + = and swizzles it onto the code already running in the simulator.
  3. Every time the injected function runs, we’re going to remove all the subviews in the main view of the UIViewController. This should clear the screen in most cases.
  4. We then run viewDidLoad to rerun our view setup code.
  5. We put this in a UIViewController extension so we don’t have to have injection functions littered throughout our app. It will be included with every view controller. That means we can press Control + = in any view controller and this code will run.

3b. Use this code instead to help with animations.

If you use CALayer for making animations, you’ll want to add the following code snippet.

import UIKit

extension UIViewController {

#if DEBUG
@objc func injected() {

for subview in self.view.subviews {
subview.removeFromSuperview()
}
if let sublayers = self.view.layer.sublayers {
for sublayer in sublayers {
sublayer.removeFromSuperlayer()
}
}

viewDidLoad()
}
#endif
}

All I’ve added is a check for sublayers on the main view’s layer, and then removed them all from the super layer if they exist.

4. Now compile and run your project in the simulator (Command + R).

You have to run the project normally the first time to load up the simulator and injection properly.

5. Next edit some view code in a view controller, like add a button.

This is where it’s time to have some fun. Add a button, throw some constraints, keep in mind that injection works with views laid out in code only. I haven’t seen it work with storyboards yet. Someone else can pick up the ball there and run with it.

6. Press Command + S on the file you changed.

This is a crucial step that is often forgotten. You have to make sure to save every file that you’ve made a change to before running the injection. My biggest recommendation here would be to change one view controller at a time if possible. Injection is powerful, but it can lead to unexpected behavior when you change too many files.

7. Finally press Control + = to inject the code into the simulator.

Congratulations! You’ve run your first injection! You can do this over and over again, it’s especially helpful when creating new UIs.

What if it doesn’t work?

Injection can be picky at times. When I get stuck I’m glad there’s an open source community behind the project. Usually you can fix what’s wrong by trying some or all of the following:

  1. Reset the simulator content and settings.
  2. Clean the project with Command + k.
  3. Quit Xcode.
  4. Delete derived data.
  5. Restart Xcode, making sure you go through all the other steps described above.

If you get REALLY stuck, you can open an issue on the github repo.

This is awesome I want more!

Well thanks for your enthusiasm! I hope you got a lot out of this article. If you’d like to learn some more Xcode tips, check out this twitter thread:

A ton of the community chimed in with their best tips and tricks. And if you’re interested in more tools like Injection, be sure to check out my talk at Realm:

And as always, if you’d like to chat, reach out to me on twitter @robnorback.

--

--

Rob Norback

Building Live Transcribe for iOS. Previously @Chime and Steady. Talk to me @robnorback. See my work at www.RobNorback.com.