adam tecle
Rebuilding an app in SwiftUI
Aug 30, 2023I spent some time rebuilding a side project app I develop called Tomato Timer completely from scratch in SwiftUI and The Composable Architecture. It was a ton of fun, sometimes frustrating, but ultimately a very rewarding experience.
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 is a lot lighter and more maintainable. The raw size of the repository went from roughly 2 GB to 800 MB.
Some topics I will probably 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.
Getting this rebuild done was satisfying because it’s something I’d been wanting to get done for a while. There are a couple new things I’m considering implementing in the next year based on user feedback, but apart from that, this project is “done” and I’m putting my side project energy towards other ideas and interests.