Stuck at Home LLC logo
← All posts
3 min read

Demolition Week: Dragging LuckyCoin Into iOS 17

luckycoinpriceguidemodernizationswiftdata
Projects
2
Commits
19
Lines
+9.2k / −59k
Files
874
Claude time
12h
Tokens
2.9M

Commits by day

MTWTFSS

Where the work went

  • LuckyCoin72%
  • Price Guide28%

This was a demolition week. The line counter says we removed more than 55,000 lines from LuckyCoin against under 5,000 added, and that lopsidedness is the whole story: this was about digging years of cruft out of the app and getting it onto modern foundations, not bolting on features. PriceGuide got a smaller version of the same treatment. Together they're the latest installment in the long, unglamorous project of keeping a portfolio of aging apps from rotting.

LuckyCoin: tearing out the iOS 14 era

LuckyCoin has been carrying code for OS versions most of its users abandoned long ago, and we finally committed to cutting that cord. We bumped the minimum target to iOS 17 and deleted the iOS 14 code path outright, then went through and flattened the tangle of availability gates that used to fork behavior across iOS 14 through 17. When an app has to ask "which OS am I on?" at every turn, every change costs more to make and more to test; collapsing all of that down to one path is what most of the deleted lines actually are.

With the floor raised, we could modernize how the app keeps its UI in sync with its data. The @Observable migration came in two rounds — first the standalone view models, then DataModel, the central object the whole app leans on. Alongside that we dropped the old ObservableObject conformance from the singleton managers. This is plumbing the user never sees directly, but it's the foundation for the app reliably reflecting state without the boilerplate that the old pattern demanded.

The other big theme was deleting things that were quietly dead. We pulled an entire old coin-browsing view cluster, stripped out the unused CoinCountView and CoinMintBranchView structs, and removed the passwordless email sign-in that ran on Firebase Dynamic Links — a feature whose underlying mechanism Firebase itself has been winding down. We also reworked the coin grids to use value-based navigation, so a coin's detail screen is built only when you actually tap into it rather than eagerly up front.

Underneath all that, we did the dependency housekeeping that modernization forces: Firebase 10 to 11, RevenueCat 4 to 5, and the API deprecations each of those bumps dragged along. We also finished ditching CocoaPods so the project is pure Swift Package Manager now, ran a couple of warning sweeps (one purely mechanical, one that turned up actual bug-shaped problems hiding in the noise), and adopted targeted strict concurrency — which immediately earned its keep by surfacing a SwiftData cross-actor crash we could then fix. Plus the usual untracking of .xcuserstate and .DS_Store files that should never have been in the repo.

PriceGuide: the same refresh, condensed

PriceGuide got a parallel infrastructure pass in two larger commits. It moved to @Observable and Firebase 11 as well, picking up the same audit fixes, and on the visible side it has a redesigned melt sheet, a redesigned splash and paywall, and a family color system tying its look to the rest of the lineup. v1.9 also shipped with refreshed App Store metadata, so this one actually went out the door rather than just sitting in the repo.

None of this week is a feature you can screenshot. It's the difference between apps that are still cheap to change next year and apps that aren't — and LuckyCoin, in particular, just got a lot cheaper.