Okay, so you’re a web developer and you know React, yeah? And let’s say building native mobile apps has always held a (literally) tangible appeal to you but for some reason (or reasons) you’ve never really gotten going with native development. Maybe you’ve tried some React Native but for some reason that didn’t really take. Perhaps just developing for the web (React in particular), the tooling, testing, hot-module-replacement, and even the much derided CSS, made developing for the web feel…well, fluid. From idea in your brain to living on a screen was a workable, fast, and pleasing process, consistently providing that great feeling of creative engineering. Engineering mobile apps? It just never came as fluidly before.
Now, React is great. I credit it tremendously for evolving the way a huge percentage of the “developing world” (my play on words for the world of all developers out there) thinks about the design of systems. It offered a declarative approach to constructing UI, while encouraging people to think more naturally about separation of concerns, bringing principles like “single responsibility” more to the fore. Its brilliantly simple API allowed people to pick up and begin executing upon its core concepts within minutes.
When it came on the scene, people were excited about React’s performance compared to alternatives at the time (e.g. Angular) in terms of DOM manipulation. But React shines not because of its performance in the browser but for its performance in the heads of the developers who wrote it. Its component-oriented, declarative approach to crafting UI made creating and engineering easier and more wonderful.
Let me try a comparison to another universe of things to perhaps explain why React Native did not stick with me. We’re all, practically all of us in the world, quarantining right now. With it, many of us are picking up new hobbies. The other night, I made my first batch of fresh pasta ever. I made the ball of fresh pasta dough, then rolled it out the old fashioned way, by hand with a rolling pin. There’s something about rolling the dough out by hand that, for lack of a better term, just feels “more right”. I recently watched the wonderful documentary Funke, about Evan Funke, the incredible pasta chef with a calling card that all of his pastas are rolled by hand. I like doing things the rustic and traditional way; even more so when they are more difficult. This may sound strange, but I am confident some of you out there feel the same way about the old fashioned way. You get closer to the essential aspects of the experience this way, feeling them more distinctly. This deepens your understanding and appreciation, and adds more to the reward.
This is what I think has ailed me in part about React Native. React Native promises cross-platform capability and a better developer experience but it takes you away, in some not meaningless way, from some essential aspects of the iOS development experience. It’s like making pasta with a machine and not truly feeling the dough. This is not a principle I hold entirely firmly to. I am not advocating that we would all be better off by dropping down into assembly and thinking in bits. But I think this does explain, at least in part, why React Native never really took hold for me.
I write this now, though, because something has changed. I work at Def Method, a consultancy in New York, and we recently started active development on projects in native iOS, using the new Apple frameworks of SwiftUI and Combine. Apple codified many of the best practices nurtured by the development community over the last few years into SwiftUI and Combine. The very existence of these frameworks can be viewed as a reaction by Apple to the ever increasing popularity of things like React Native, with an acquiescence to the fact that the development experience on their platform was lagging far behind. For me, beginning to work with them, in this new way, has been a revelation.
So let’s get back to you, React Web Developer. If you’re like me, you’ve maintained a desire to construct mobile apps but React Native never took hold, and straight native development always seemed to present too big a barrier. However, with these new tools, native iOS development now has a developer experience that feels fluid in its connection between programmatic UI and visual feedback.
For you, the React developer, perhaps the best thing about SwiftUI is that it will feel familiar. SwiftUI applies declarative programming of UI structures. You build a series of Views that will feel eerily similar to components in React-land. It allows for a hot-module-replacement-like experience with Previews (using the nifty feature known as “Dynamic Replacement” - for a deeper dive on the Apple origins of Dynamic Replacement click here). Finally, SwiftUI and Combine are built with the philosophy of being “reactive.” Your views, rather than being a reflection of a sequence of events, are now a reflection of state. This makes your code, which handles the UI, easier to reason about, and this leads to cleaner system design. It also makes UI far easier to test and for a great video on that topic, check out this talk one of our engineers, Paul Ort, gave recently on UI Testing in the new SwiftUI framework.
SwiftUI views are reactive. They re-render with updates to observed stateful objects or data. This all feels very “Reacty.” Combine is the new framework from Apple that provides tooling to manipulate and transform data in a FRP (functional reactive programming) way. If you’re not quite sure what that means but you’ve done some Redux with your React, consider how Redux actions get passed to a reducer, which is just a function that returns a new state. A new state is generated in a functional way by reacting to a new action. The basis for many of Combine’s ideas can be seen in earlier third party tools such as RxSwift.
This combines to create a development experience in native that feels pretty natural, while rivaling the ease you’ve grown accustomed to on the web. Now don’t get me wrong. You’re most probably going to struggle, especially if you have limited to no experience with Swift. If that is the case, I highly encourage you to take some time to develop a solid base layer of understanding of the language (Paul Hudson’s 100 Days of SwiftUI is highly recommended). This will help you to discern when new concepts appear if they are from the language or one of these new frameworks. Then when working with Combine, you’ll have to wrap your head around the concept of Publishers and Subscribers. My super short and perhaps pithy advice: don’t overthink it! A publisher is a publisher. It does exactly what it sounds like it does.
For some help getting going, check out this iOS starter template repo in SwiftUI and Combine and the accompanying backend Rails API starter template repo. Additionally, I’ve linked to some helpful learning resources below.
In closing, it is maybe worth pointing out the exceedingly obvious: when you do begin to work in this way, you’ll be rewarded by seeing the evolution of an artisanal mobile app that you’ve created. This is something you can put in your hand, carry in your pocket wherever you go, and interact with with your fingers. You can feel it and you’ll know that it has been made in the most authentic manner, like a batch of hand-rolled pasta, and this is the truly great satisfaction of it all.
P.S. I’m linking to some of the more helpful resources I have come across in my padawan’s journey so far into the realm of SwiftUI and Combine:
- Paul’s talk on SwiftUI and UI testing - talk
- Rey Wenderlich’s store has some excellent books, currently on sale for %50 off. I recommend the SwiftUI and Combine books highly.
- A really nice post using a playground to visualize publishing and subscription behavior Visualize Combine Magic with SwiftUI Part 1 - Flawless iOS - Medium
- A whole series of posts focused on Combine, helps lay a deeper more solid understanding - https://www.donnywals.com/category/combine/
- This book is the most comprehensive documentation I’ve found for it all in one place. This may be the one place to go to if you’re going to go anywhere, of what I’ve found so far: https://heckj.github.io/swiftui-notes/#introduction
- A really great article on data flow in SwiftUI - works off of coming from an RxSwift background (which may be a lot to sift through if you don’t have that background but it still provides nice comparative context): https://kean.github.io/post/swiftui-data-flow
- “How to Test Combine Publishers” - this article really helped me finally write a successful test for a viewModel publishing properties - the asynchronicity was really throwing me for a loop: https://medium.com/better-programming/testing-your-combine-publishers-8ccd6bd151b
- Donny Wals on testing combine code: https://www.donnywals.com/getting-started-with-testing-your-combine-code/
Also some other meaningful reasons why React Native may not be your choice: