React Native, Native

Making your Swift app more React Nativey

Confessions

I’m going to let you in on a dirty little secret. Sometimes I think longingly about React Native.

I know, I know. Feels so wrong. But some of it feels so right. Reactive, declarative UI code? Hot reloading? Updates that can bypass the app store? And even though Javascript isn’t as sweet in a lot of ways as Swift, it’s getting pretty good (new async/wait and gradual type checking with Flow). I keep trying it out from time to time, wanting it to be amazing and save me from all the things that drive me nuts in iOS development. Of course it’s not without its share of cons, but certain features are awful fun and productive—and who doesn’t want to have fun and be productive?

For those of us who decide React Native is not the way, what if we could get some of the features while still writing Swift? Today we’ll explore how we can have a reactive, declarative UI code and hot reload app data so we can save tons of testing time. Also, maybe we can do something to bypass the app store for updates even just a little?

Reactive, Declarative UI

React Native lets us write UI code that feels more like a description of what the UI should be, separated from the logic that configures and transforms all the data. We don’t have the fancy virtual DOM React does, but we can work around that.

Reactor is a small Swift library I wrote inspired by Elm, Redux, and the work on the excellent ReSwift by Benjamin Encz and others. See the documentation for a more in depth understanding of Reactor, but the basic model we’re working with is this:

In a nutshell, we have one state object with all of the application data nested inside of it. Each of our view controllers has an update function that knows how to take the state object and update its view. The view controllers subscribe to the Reactor, which notifies them whenever the state changes.

An example of this update function might look like:

All UI updates go in this function. This gives us one easy place to declare exactly how our UI reflects the app data. It will always stay up to date, reacting to the any state updates.

If this hasn’t all settled in yet, don’t worry. Going in depth here is beyond the scope of this article. Read the documentation and ping me on twitter with questions. And if you don’t like Reactor, ReSwift is terrific and the pattern is simple enough you can easily roll your own. The point is, if we store our application data in one data structure, we can have simple reactive, declarative UI code in Swift without React Native or a mind bending FRP library that may scare co-workers away (but make you sound super smart at dinner parties).

Hot Reloading

We cannot, due to Swift limitations, hot reload recompiled code. Bummer.

But, we did just talk about representing our application data as a struct. What if, hypothetically, we could serialize/deserialize our entire state into some format—say… JSON—save it to the file system, and then watch that file for updates? Then, hypothetically, we could edit that JSON file in our favorite text editor and our app would automatically update using our Reactor architecture.

Hypothetically. Right?

Enter the amazing KZFileWatchers by Krzysztof Zabłocki. Observe:

Hot Reloading Application Data

Check out the example project to see how it’s done. But it’s pretty much exactly like you might imagine: our state is designed to serialize/deserialize using Marshal, and then we use the hook it all together with our architecture and the file watcher.

I think there’s a lot of potential here: recreate buggy states users report, testing UI without having to recompile, easy inspection of your apps current state… all kinds of fun stuff.

Bypassing the App Store

We’re quickly approaching the end of the known iOS universe.

Javascript, due to its interpreted nature, not only can hot reload code, but can hot reload code that has been received over the network. This leads to a whole realm of possibilities for A/B Testing, bypassing the app store for some updates, and security vulnerabilities. :P

As we’ve dicussed before, we can’t hot reload Swift code. We do know we can hot reload application data, however. So, what if we represented more of our UI as application data? Maybe we could write a few reusable components, and the data itself would tell us which UI component it wants to use. This is something that Spotify is doing, as demonstrated by John Sundell. Watch that video. Cool, cool stuff.

Conclusion

React Native takes some heat from the iOS community; probably a lot is undeserved from developers who haven’t tried it, but like all tools it comes with its own pros and cons.

Maybe those cons outweight the pros for you in your project. That doesn’t mean we shouldn’t covet the pros or try to figure out how we can apply the ideas amazing software developers in other areas to our own domain.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.