Slug rob nordback header

Three Tools for Swifter Swift Development

Speed of development has always been a struggle for iOS. When web developers build the same feature in half the time, it’s hard not to get jealous (until you think about all those dependencies 😜). In this talk I’ll cover ways you can strategically cut down your compile times, quickly build scalable UIs, and dynamically mock out your APIs in the blink of an eye.


Introduction

Today I’m going to talk to you about three digital tools for swifter iOS development. The first thing I wanted to do is give you a little bit of background about myself. I work at Chime Bank as a senior mobile engineer. I help people save money and live healthier financial lives.

I’m going to talk to you today about the workflow I built at Chime for activating your debit card. This is one of the first flows that users interact with. I really enjoyed building it because I knew I was going to get to touch every user’s experience as they went through signing up for our bank. The basic breakdown of building the debit card activation can be looked at as follows. I had to integrate with the backend, build the UI, and then perfect the UI.

We’ll be talking about Mockable, a tool that can give us a lot more control over our backend.

Long compile times can really slow us down when we’re building the UI, so we’ll look at Injection to help this process go faster.

And when perfecting the UI, sometimes you and the designer can have different opinions on what is perfect. I’ll introduce you to a tool called Flawless that will make it so you can get a pixel perfect design every time.

I have a little secret to share with you before I hop into the talk. While I was preparing for this talk, every single one of these tools broke on me this week! I had to ask myself a question: if I wasn’t giving a talk on three tools for iOS development, would I really use these tools if they’re going to break like this?

Once I got back in the saddle and got everything working again, the definitive answer for me was yes, and it was for one simple reason: Every time you improve your developer experience, that means you make it possible to build a better user experience. Whenever you are able to build features faster, or iterate faster, or make small changes more easily, you’re more willing to iterate over and over again. That is what gets you to that optimum user experience. That’s the reason why I’m really excited to talk to you about these three tools tonight, because if I can improve your developer experience, that means that I can also help you improve the experience of your users.

Integrating the Backend using Mockable

Let’s start with our story of building the debit card activation. The first part is integrating with the backend. We had several states that this widget can occupy. It can be in a processing state, ship state, or activated state. In addition, this widget may have to disappear on the home screen, and then a new widget would come in saying “add funds to your card” at the end.

Get more development news like this

With all of these state changes, I wanted to know if my UI was going to perform well when the server changed its data. I thought about a couple different ways I could tackle the problem of testing this. We already use a testing framework called Moya at Chime. Moya allows you to mock endpoints pretty easily. But the problem I had is that I wanted to dynamically update my endpoints. I wanted to make it so that I could change something, and pull the refresh, and I could see a new screen right away. To do this, I could have built a complicated UI overlay. But we do this so much at Chime, I didn’t want to build something halfway. I wanted to build something that would be reusable over and over again. Even better, if I could use an existing tool, I would look to it.

An app called Mockable came to mind while I was trying to address this problem of testing all these different states. I already sometimes used Mockable to add a mock endpoint during interviews with candidates. It was really easy to use. It allowed me to change those interviews on the fly. So I decided to give it a try. And here’s what I came up with in about ten minutes. I had three endpoints that related to all the statuses that the widget I was building could be in. And I was able to render them on the screen on the fly, just like this:

I’m changing the endpoints that are currently activated. Then, I’m changing to the card status widget, to make sure it works and is in place. Then I’m changing it to check that the different states of the card status widget work. Finally, we had a state where if you didn’t receive your debit card for some reason, you could contact us saying you hadn’t received your card.

This was so simple and so easy to use! The Android team and the iOS team at Chime now use this when we’re first mocking out endpoints for basically every feature we build. There are a few tips, though, that I wanted to share with you for making Mockable easy to use in your apps.

We had to make sure that we switched onto the Mockable endpoint whenever we were testing. The easiest way to do that was to set up a preprocessor macro. This code switches over the endpoints that we point to in Moya, allowing all of our data to just point to Mockable:

#if PRODUCTION
	kChimeAPIType = .production
#elseif STAGING
	kChimeAPIType = .staging
#elseif MOCKABLE
	kChimeAPIType = .mockable
#else
	kChimeAPIType = .test
#endif

You can actually couple this preprocessor macro with a schema, so that now all you have to do when you want to test drive something new is run the Chime Mockable schema, and you’re good to go.

One last tip for using Mockable is if you want to have dynamic endpoints with something like a user ID, then you want to use these curly brackets in order to make your endpoints accept random data from the user, like this: /user/{user id}/endpoint.

The reason why I wanted to share Mockable with you, once again, is because a better developer experience is going to result in a better user experience. We used to complain when our product manager would come to us and say, you know what, we have to change everything the backend is throwing at you - we have to just change that data structure entirely. And now, it’s not really a problem. All I have to do is talk with the backend engineer, and we can throw together a json payload for Mockable in minutes, and I can get coding. It allows me to move quickly, and not worry about those changes that inevitably come from the project managers. So once again, the better DX equates to better UX.

Building the User Interface using Injection

After building the backend, the next stage of development is building out the UI. The Chime app takes about ten seconds to compile, and it also takes time to attach to the simulator. That’s about 20 seconds total. That’s a long wait time for building a UI!

The next part of the app I had to build had a flow of a lot of static screens. I thought to myself, is there anyway I can get rid of these atrocious compile times? I did a lot of research. One of my favorite articles was drunken Swift, where someone was able to set up the Swift compiler to take 12 hours to compile a piece of code because of the complex type it had given it to interpret. So I made sure to specify my types. Also, there are some flags you can flip in your settings to help with these compile times.

Why are long compile times are so damaging? Let’s insert the mandatory XKCD slide here.

The problem with compile times is that they’re an excuse for slacking off. You can be “nerd sniped”. Twitter is really attractive during those 20 seconds for some reason, you know? You’re thinking you could just check you email, go to Twitter, have a sword fight, one of those things. When you decrease that run loop, you really increase your effectiveness, because you’re not taking a ten minute break on Twitter while you’re trying to build this UI.

You really can’t beat this tool called Injection for reducing compile time. This app was a part of Xcode tools, but in Xcode 7, they got rid of it, so John Holdsworth built a standalone app that you can download now. It works with Swift, and allows you to swizzle your code in real time onto the simulator. I want to give you a quick demo of how that works.

First I comment out the entire bit of code from the view that you saw before. Now, I’m adding an image view, and then adding constraints for each one of these pieces of the screen. You’ll notice it’s not taking 20 seconds every time, it’s actually taking just about a second to get that look on the screen. It’ll keep building as I talk. The real win here is that your run loop becomes one second long. You can adjust colors and layout, you can change your constraints, you can pretty much do whatever you would need to do with this app, while building a static UI.

It can also be used for UI’s that move, for example a scroll view, or collection view, or table view. You have to set it up slightly differently, but it still performs. There’s a caveat here: if you don’t get the text view sized quite right, for some reason, at the very beginning, it will not resize with injection, unfortunately. But these are little problems that don’t get in your way too much when you’re building.

As I was talking, we just built an entire screen in about a minute. That is pretty cool! I’m hoping that this demonstration is dramatic enough that you’re convinced that Injection is a pretty sweet tool. The way you actually end up using Injection is very interesting as well. All you need to do is use this function called Injected. Whenever you tell Injection to run its code, it’ll run all the code within this function. What we figured out was that if we ripped out all the subViews of the view, and then ran viewDidLoad again, we could get the best performance:

@objc func injected() {
	self.view.subviews.flatMap {
		$0.removeFromSuperview()
	}

	viewDidLoad()
}

Otherwise you’re injecting little pieces on top of what you already have on the view. That can look weird and not work right. So this is the essential ingredient that we added to Injection to make it work with our app.

Then, you have to run the simulator with that Injected function in place. And then all you have to do is press command S, and control equals. Every time you do that it will save the file, swizzle it onto what’s already in the simulator, and run it.

We don’t want this code in our production apps, so we made sure to wrap it in our preprocessor macros. We also threw it in an extension of UIViewController, because this basically only works extraordinarily well with UI views. I think it can work with other files as well, but the main thing we were concerned with was views. So if you put it in an extension for UIViewController you can use it in table views, view controllers, collection views, anywhere you want. You just have one piece of your app in a separate file, and it works everywhere.

So, that’s Injection as a tool! It made building those UI screens much, much easier. I was able to build them in far less time than I would’ve been able to otherwise. So when the project manager came to me and said, well, we’re going to rearrange those views, rip out two of them, and add three more, I didn’t get absurdly frustrated. Maybe a little frustrated! But it wasn’t that big of a deal. Because I had good developer tools, and a good developer experience. So I was 1) enjoying myself, because it’s kind of fun when Injection works really well, and you’re just messing around in the screen in almost real time, and 2) we’re not having that friction in our conversations. He’s able to push the UX further, and I’m totally willing to play ball with him. I’m not saying “you know what, you’ve changed this 10 times on me already, I really think we should just ship it”. So, once again, the better developer experience is leading to the better user experience.

Perfecting the User Interface using Flawless

Now let’s talk about perfecting the user interface. Oftentimes, designers and developers can have a different opinion on what things should look like. I can run into issues with trying to hit the right look for all the different screen sizes. I have to talk with my designer, and say, “hey, this looks all scrunched on the 5, and on the 7+ this is looking crazy”, and so she’ll make me specific mocks for what those screens should look like. But the problem is getting them pixel perfect. Instead of guessing, and having to repeatedly check back with the designer, it’s much more efficient to use a tool like Flawless. With Flawless, that problem no longer exists. You can simply see the UI that you’re building right in the simulator. You can go far as to what the screen should look like with tools like Zeplin, or InVision. [Demonstrating Flawless] But as you can see with Flawless, when I go back and forth, I can tell that I’m a lot closer than just trying to eyeball it.

What I like most about Flawless is this split feature. Zeplin has a very similar feature that I just recently found.There’s a button at the bottom right. There’s no tutorial that tells you it’s there, but it is there. So if you use Zeplin, you already have a tool like this that lets you overlay views on top of your simulator. What’s cool about Flawless is it allows you to do this side by side right in the simulator:

What you’re seeing right now is I’ve combined Injection with Flawless. There was no compile time in there. I was able to hot reload while making tweaks to my UI, while using Flawless, which is pretty nice.

This all comes down to giving the developer more time. A better developer experience is what’s going to allow you to build better user experiences. You’re going to have more time, you’re going to enjoy yourself more, and you’re going to be able to push your designs to a higher level. You won’t just settle for good enough. You can push your designs to really delight the user.

Cost of Tools

To recap, we’ve talked about using Mockable to mock out your backend dynamically, so that you can be in full control of the data you’re dealing with. We also talked about building UIs with Injection, so that you can build them extremely quickly, without having to wait on those 20 second compile times. And we also talked about perfecting the UI with Flawless so you don’t have all that back and forth with your designer, saving you time and the hassle of getting pixel perfection.

My question to you is, which one will you choose? What I’m hoping is that this talk is just in time. I really like immediately applicable talks, because then I think about what tool, or what piece of this can I take and use tomorrow in my code base? I also want to put this out there, because I know as developers we often don’t like to pay for stuff… To be clear, I don’t work for any of these companies! I just think they’re really awesome tools, and I wanted to share them with you. Some of them do cost money. Injection is totally open sourced and free, and a fantastic app. You absolutely should use it. We use Mockable extensively. We were able to use it recently in our Hackathon to create a bunch of different prototypes, without the help of our backend developers. That was really cool! It costs us $12 a month in order to have that functionality. We think it’s worth it. And then, Flawless is a $15 app with a one-time purchase. I’m no longer using Zeplin because we migrated to InVision just recently, but I really wanted that tool from Zeplin, so I was willing to pay 15 bucks for it. The mentality I have around buying tools for development is simply that I’d rather pay somebody else to develop these awesome tools, while I get to work on saving people money, and giving them better financial lives. That’s the problem I’d rather be solving than my compile times. That’s why I encourage you to think about paying for these tools. And think about paying for tools, in general.

Now, I might sound like a broken record, but I wanted to give a little caveat. I’m not saying roll over and take 500 spec changes, okay? No one’s going to be happy if the project manager changes your spec about 20 billion times and you’re just exhausted, and can’t go on. I’m just saying that if you improve your developer experience, and are constantly working on it, you’re going to end up building better products. Your users are going to be happier because of it. Thank you so much for your time and attention!

Q&A

Audience Member: I’m just curious, you’re using Xcode 9. I’m just starting to use Xcode 9 because the golden master came out. Apple promised that with Swift 4 there would be magical quantum leaps in compilation time. So did that happen?

Rob: I did get an improvement with compile times on Xcode 9. That is a caveat I want to give. All the demos I did were on Xcode 8, because Xcode 9 was still in beta while I was writing most of this talk, so I decided to use something stable. Especially with Injection, John Holdsworth is really on top of it. He even has a version of the app that works with Xcode 9. So definitely check that out, but there is an improvement with compile times on Xcode 9.

Audience Member: Hey, thanks for the talk. I noticed in some of your demos that in your actual view building process, you’re using some kind of very fluent API-like extension on top of the UIKit. What was that?

Rob: I was hoping to add that to the talk but it didn’t quite fit with the flow. That was Snapkit. I enjoy using Snapkit with InVisions in specs. I use the percentages in specs because it allows me to combine Snapkit with a frame base layout to resize my views to any screen.

Audience Member: You mentioned a couple things that you couldn’t change with the swizzling in using Injection. Do you know what the limits are, or what types of things can be changed, and what can’t be? I think it was in Injection, there are certain properties on UI elements that you said would not change when you swizzled them?

Rob: There are a couple of idiosyncrasies. I’m not exactly sure why they don’t work. The main one that I ran into while I was building that particular component was the text view. For some reason it wouldn’t resize after I set the constraints the first time. I’d have to think about that one a little bit harder to see exactly why that was. Besides that, you’re able to change multiple files. But you have to make sure you save all those files, and run Injection in the file that has a ViewController that you’re looking at. It doesn’t have a lot of limitations UI-wise. But if you’re going to change the backend of your app, and the front end to try to get a change, it’s probably not going to work for you. It makes you split up your backend and your frontend work. That said, you can actually use Mockable, Flawless, and Injection all at the same time to dynamically update your views and work on different views while you’re going through your app, and not have to recompile.

Next Up: Explore SwiftLint: Realm-Supported Open Source Tooling

General link arrow white

About the content

This content has been published here with the express permission of the author.

Rob Norback

Rob Norback is a Senior Mobile Engineer at Chime Bank where he enjoys helping people save money. Previously he helped AdHawk grow from zero to profitable in a year and a half. In his free time he likes to travel with his wife and build puzzles.

4 design patterns for a RESTless mobile integration »

close