I’ve had a lot more free time in the last few weeks so really doubled down on my iOS adventures with Swift, Rails 7 and Turbo Native! In my first article about this journey, I left off somewhere deep in a quagmire of confusion and architectural patterns MVC, MVVM, MVVM-C patterns, and to be honest, it wasn’t too fruitful.
Emerging from the Rabbit Hole
In the end I was looking for something that didn’t exist, since in my imagination MVVM-C was nothing like the reality. What I did learn though was building a simple app 4 or 5 times with different patterns and watching and reading a LOT of tutorials, was that some of the fundamentals started to stick. These heavily used concepts like “delegates” and “extensions” started to click.
I went back to the basic MVC version, with a simple
SceneDelegate that handled all the set up of my basic app and went about
trying to add native authentication to my app.
The way Turbo Native works with Rails 7 is magical. It just works out of the box, and for very simple apps you can be up an running in a matter of hours if not minutes. If you just want a quick look, try Joe Masilotti’s excellent Turbo Native Xcode Template that will literally have your existing app running on iOS in 5 minutes!
The way Turbo Native apps work is there is a simple native wrapper around a web view, and you can sprinkle in native iOS (or Android) features as you wish. So in the case of authentication - ie signing in - you can happily sign in to your app on the iPhone in this webview and the session will keep you logged in.
Sometimes though you may need to call your Rails backend with an API outside of the browser session - in my case I want to access Apple Health data via HealthKit and post the data to my backend Rails app. This is where “Native Authentication” comes in. You need some kind of token from the iOS app that you can send over to your server along with API calls so the backend can securely identify which user the request relates to. For most interactions in the webview this is all handled with cookies as it is with a webapp, but API calls need special treatment.
Rather than a simple username/password sign in form, when I built the webapp, I really wanted a “password-less” flow where a user just enters their email address, clicks a button and then receives a 6-digit code via email that they then need to enter on another screen.
I really like this kind of flow as a user because I don’t need to remember yet another password, but I like it even more as a developer since we get to validate the user’s email address automatically, and also we don’t have the sign in/sign up confusion. Just enter your email address, get a code and you’ll either be registered, or signed in if you have an account already.
Of course, I wasn’t really thinking about native auth when I made this for the web, but now I had to learn about native views and navigating between them. Good news is I got this working with nice native SwiftUI modals, and that was a huge motivator as well as a great way to understand some of the Swift/iOS concepts.
I’ll write a technical post about this soon. (UPDATE: check out Password-less SwiftUI Native Auth with Turbo iOS )
Now I had a way to store a token in the iOS app and post JSON to my Rails API, I needed to figure out how to collect the data from Apple Health on a device, package this up and save on the backend. After quite a lot of trial and error, I now have this working in basic form, and just today was able to get all of my Workouts, weight measurements and steps info from my actual iPhone posted to my local server.
This is all very exciting, but every small step opens up another myriad of questions and challenges. For example currently I’m trying to figure out how to use both workouts - which include calories burned - and step counts which do not, as source for my overall calories burned calculation, without double counting steps, since workouts obviously involved some stepping!
Here’s what some of the data looks like so far in the app, plotting calories consumed from meals in the meal plan in the webapp alongside calories burned from workouts and weight from HealthKit!
I’ll write a technical post about this soon too!
I’m really enjoying learning swift, applying to a problem I really am passionate about and trying to make a tool at the very least just for myself to use. Every step of the way I’m definitely uncovering more challenges but enjoying the process.
Running my app on my actual iPhone and getting all the Apple Health data back to my Rails app feels like a big milestone so I’m really excited to spend more time on this over the next month or two. Stay tuned!