Bringing Your Turbo Native iOS App Offline
My side project is called Smart Strength. It’s the workout app I always wanted, but for some reason, other people want to use it, too (mainly because of the ability to share your workouts with your coach).
The app, at this moment in time, is not at the quality level I hold myself to. I mainly just wanted to build an app with Turbo Native and SwiftUI. I took the indie hacker’s advice to get it out there as soon as possible.
Two years have gone by, and I’m much wiser. Not only have I built far more iOS apps, but I have also built some Android apps (using Turbo Native).
To my surprise, people use Smart Strength, not many, but enough for me to think there is a kernel of an idea to pursue. The first request people have asked me about is using it offline(or in an area where network coverage is poor).
Most of the world still has terrible internet speed, so offline makes sense, even in a wealthy country like mine.
This post will cover how I approached building an offline iOS Turbo Native app. Smart Strength version 2 will use some of the techniques here. I hope that I will ship it to the public in February.
Do you need offline access
If you are building a Turbo native app, ask if you need offline support. If the answer is yes, then you have to figure out if the user needs to be able to write content.
If the answer is no, it may be possible to save certain html pages to disk and server them using WkWebKit. This has some drawbacks due to style changes, but it is possible.
You could build some sort of proxy server described by 37 Signals(which is beyond this blog post).
If you can write locally, you must render a native screen and store data locally. This is the situation I found myself in with Smart Strength.
Picking a data storage strategy
The first challenge I ran into with iOS and offline access is that many paths exist. While Google has established what to do with Android(even in their beginner course), Apple’s developer docs are designed around getting you to use online backups with iCloud.
If you want to use your server with the typical Rails setup, you need to figure a lot of it out yourself. There are a lot of edge cases when it comes to syncing data, but none of them are beyond the wit of man.
For Smart Strength, I explored using Core Data and SwiftData, but instead placed my bets on Sqlite.
Here are some reasons why:
- Sqlite uses SQL, a syntax I’m familiar with as a Web Developer. Core Data and SwiftData offer a new query DSL that is, in my opinion, inferior to SQL.
- Sqlite allows backups to remote servers
- Sqlite knowledge transfers over to Android
- SwiftData and CoreData tie you further into the Apple ecosystem
- Sqlite has a proven track record, while SwiftData is new
- SwiftData has too much magic compared with SQLite
- There is a good ecosystem of Sqlite swift packages
- I wanted to implement a similar pattern to Active Record, namely callbacks and relationships via classes
Ultimately, I settled on the GDRB library, which provided everything I needed.
- Callbacks (for syncing data to the server)
- Ability to use SQL
- Well Documented and Maintained
In the next post, I will demonstrate how to use it.