adam tecle
Rebuilding an app in SwiftUI
Aug 30, 2023I spent some time rebuilding a side project app completely from scratch in SwiftUI and The Composable Architecture. Full rewrites are usually a bad idea, but being that the app was relatively small and my only goal was to learn and have fun, I went full steam ahead.
Fortunately, I managed to ship the rewrite, I learned a ton, and I had fun doing it. Mission accomplished.
Some of the high level changes to the codebase that I made:
- Removed RxSwift in favor of Combine + async/await
- Replaced Realm with CoreData (because I wanted to implement iCloud sync). This was my first time working with CoreData and CloudKit.
- Replaced CocoaPods in favor of SPM
- Replaced ReactorKit with The Composable Architecture
- All UIKit code rewritten in SwiftUI
- Removed fastlane, using Xcode Cloud for CI/CD needs (which I may re-evaluate once it’s no longer free after December 2023)
- Dynamically generated workspace with tuist
I added some new features and new screens, but because of SwiftUI, TCA, and the removal of a bunch of really bulky dependencies, my codebase became a lot lighter and more maintainable. The raw size of the repository went from roughly 2 GB to 800 MB.
Some topics I want to write a bit about in the future - e.g. figuring out a testable approach to using CoreData and TCA, implementing a somewhat complicated sequenced and state-driven animation.
One thing I really enjoyed about TCA is how it let me break things down at the Reducer as well as the View level. It’s great to be able to write a SwiftUI view like this, which is a view that encapsulates 2 types of timers.
struct TimerView: View {
let store: StoreOf<TimerReducer>
var body: some View {
SwitchStore(store) {
CaseLet(
state: /TimerReducer.State.standard,
action: TimerReducer.Action.standard,
then: StandardTimerView.init(store:)
)
CaseLet(
state: /TimerReducer.State.stopwatch,
action: TimerReducer.Action.stopwatch,
then: StopwatchTimerView.init(store:)
)
}
}
}
With TCA it’s really easy to have a clean separation of concerns.
This undertaking was really satisfying to complete because it’s something I’d been wanting to do for a while. It also really feels great to have users write in to say they enjoy the app or to suggest features and improvements. The app definitely isn’t perfect and there is so much more I could do, but in the interest of being able to put time and energy into other ideas and interests, I’m calling it “done”.