Skip to content

Ten years, three apps, one evolution

From Objective-C to SwiftUI, from CocoaPods chaos to Swift Package Manager, I've built three iOS apps that span a decade of platform evolution. Here's what breaking production taught me about dependency management,…

I've spent the last decade building iOS applications, and my GitHub repositories tell a story that every product engineer will recognize: the relentless march of platform evolution, the pain of third-party integrations, and the constant tension between shipping fast and building things the right way.
Three projects:
Stormy-Travel-Time (2015-2026): A weather and travel app born in the Objective-C era
GoingVegan (2023-2026): A vegan lifestyle companion with restaurants, recipes, and gamification
PetSafe (2026): A pet food safety scanner leveraging barcode APIs
Together, these apps add up to over 150 commits, 23,000 lines of Swift and Objective-C, and countless hours debugging authentication flows that only fail in production. Let me walk you through the lessons.

The three apps: a technical overview
Stormy-Travel-Time: the legacy survivor
Starting in 2015, Stormy-Travel-Time was built when UIKit was king and Objective-C was still the lingua franca. Over 57 commits spanning 10 years, this app evolved through multiple architecture paradigms. The git history reads like a timeline of iOS development itself: initial Objective-C implementation, Swift migration, experiments with ReactiveCocoa, eventual removal of reactive patterns for direct URLSession calls, and the never-ending battle with Google Maps SDK binary size (more on that in a later section).
Stats: 57 commits, ~3,200 lines of code (mixed Swift/Objective-C), UIKit-based architecture, Google Maps integration, OpenWeather API integration.

GoingVegan: the maturing product
Launched in 2023 during the SwiftUI renaissance, GoingVegan is where I made the transition to thinking like a product engineer. With 89 commits over three years, this app includes sophisticated features: map-based restaurant discovery with Yelp integration, AWS-backed recipe database, streak mechanics and gamification, Sign in with Apple and Google authentication, subscription management and paywalls, and accessibility-first design patterns.
The commit messages tell a story of iteration: multiple sign-in integration attempts, performance optimizations for map rendering, extensive accessibility work, and data synchronization challenges between Firebase Auth and CoreData.
Stats: 89 commits, ~7,600 lines of Swift, SwiftUI + CoreData, multi-provider authentication, AWS API integration.

PetSafe: the modern sprint
Built in just four weeks (January 2026 - February 2026), PetSafe is my most recent project and uses the current state of the art in iOS development. With 14 commits and ~13,000 lines of Swift, this app leverages modern tooling: SwiftUI + SwiftData (Apple's newest persistence framework), barcode scanning with AVFoundation, USDA and OpenFoodFacts API integration, subscription infrastructure with StoreKit 2, and test-driven development from day one.

Despite being the newest, PetSafe is also the largest codebase, which shows how much infrastructure modern iOS apps require out of the box.

The patterns that emerged: common challenges across a decade
Analyzing the git history across all three projects revealed five recurring challenges that transcend any single app or technology choice.

1. Dependency management: the silent productivity killer
Stormy-Travel-Time's commit history is a graveyard of dependency management attempts. The app went through CocoaPods, experimented with Carthage to reduce binary bloat, attempted manual framework integration, then circled back to CocoaPods. Each migration consumed days of work and introduced new failure modes.

The data backs this up: CocoaPods alters project files and introduces merge conflicts, while SPM produces binaries approximately 20% smaller than other solutions. By 2025, CocoaPods entered maintenance mode, with no new versions planned past Q2 2026. This means Stormy-Travel-Time's 10-year journey tracks the entire lifecycle of iOS dependency management tools from inception to deprecation.

PetSafe, built entirely with Swift Package Manager, shows how much easier life has become for iOS developers. No workspace files, no pod installs, just a dependency declaration and a build. But GoingVegan still uses CocoaPods for some Firebase dependencies, creating a hybrid approach that works but feels like technical debt.

2. Third-party SDK integration: when 'just use their library' isn't simple
The Google Maps problem: Stormy-Travel-Time has multiple commits trying to shrink the Google Maps SDK, which adds an average of 5.7 MB to IPA size and 18 MB to install size. The commit messages are telling: "Shrinking GoogleMaps size," "downgrading to googlemaps version 10.5.1 in hopes of smaller framework size," "removing cocoapods and manually adding frameworks." None of these attempts made a dent. The SDK is just a big binary.

The authentication integration maze: GoingVegan's git history shows the pain of authentication integration: "Got Sign In With Apple working" (success!), "Fixed the data issues with sign out" (oh no), "Cleaned up code and got google sign in to display calendar correctly" (wait, the calendar?). Authentication involves far more than OAuth flows: token management, account deletion requirements, handling partial user information, and dealing with the fact that Sign in with Apple only returns credentials on first sign-in. Some 85% of developers report problems managing API response errors, and authentication flows are the perfect storm of state management, security requirements, and platform-specific quirks.

3. UI consistency across devices: the eternal screen size battle
All three apps have multiple commits about layout issues, screen size adjustments, and cleaning up UI for "all devices." GoingVegan alone has: "Fixing ui on other screens so it dynamically adjusts to screen size," "Fixing screen size issues on log in screen," "cleaning up home screen so it works with all devices." SwiftUI's promise of adaptive layouts helps, but the reality is messier in practice. Simulator testing isn't enough; you need to test on actual devices with different screen sizes, safe area insets, and dynamic type settings.

4. Data persistence and state management: the synchronization nightmare
GoingVegan's "Fixed the data issues with sign out" and "Potential fix for unloaded code. Will need to continue to test and see" commits point to a fundamental challenge: keeping local state synchronized with remote data, authentication state, and UI state all at the same time. Using CoreData, I hit issues with context threading, optimistic UI updates that failed to sync, and the classic problem of signing out while network requests are still in flight. PetSafe's use of SwiftData simplifies some of this, but introduces new challenges around query performance and @Query property wrapper behavior.

5. Build warnings and technical debt: death by a thousand papercuts
Across all three projects, there are countless commits about "cleaning up warnings," "warning hunting," "resolving all errors," and "correcting warnings." Warnings are insidious because they're easy to ignore right up to the point of failure. In Stormy-Travel-Time, ignoring forced unwrapping warnings led to production crashes. In GoingVegan, deprecation warnings meant entire sections of code needed refactoring when Firebase updated their API. The lesson: treat warnings like errors, or pay the technical debt later with interest.

The hardest challenge: platform migration under pressure
If you asked me to rank the challenges, dependency management was the most persistent, authentication was the most frustrating, but platform migration was the hardest problem. Here's the reason.

Stormy-Travel-Time started in Objective-C in 2015. By 2020, Swift was the clear future, and the codebase needed to follow that path. The commit "First swift update" marks the beginning of a multi-month migration that touched every file. The challenge wasn't the language syntax. It was the architectural decisions baked into the Objective-C code that resisted a clean translation.

Objective-C encourages massive view controllers, manual memory management thinking, and dynamic typing. Swift wants value types, protocol-oriented design, and compile-time safety. Bridging these worldviews while keeping the app functional for users meant running a mixed codebase for years. The git history shows the reality: "resolving all errors. Now targeting warnings for cleanup," "resolving all issues except googlemaps error," "All but 3-4 warnings. Still builds and works."

The GoogleMaps error that persisted across multiple commits? It was a bridging header issue that only manifested in release builds. Tracking that down required understanding the Objective-C runtime, Swift interop, and Xcode's build system internals.

This experience shaped how I approached GoingVegan and PetSafe. Both were built Swift-only from day one, with clear architecture boundaries and value-type-first design. When SwiftUI emerged, I could adopt it incrementally in GoingVegan rather than facing another big-bang rewrite.

What ten years taught me about product engineering
1. The platform will change faster than your app
In 2015, Objective-C was the standard. In 2020, SwiftUI was the future. In 2026, we have SwiftData, async/await, and Observation framework. Your 10-year app will outlive multiple paradigm shifts. The engineers who thrive are those who can evaluate new technologies pragmatically: not every shiny new framework is worth adopting, but ignoring platform evolution means your codebase becomes legacy ahead of your product.

2. Third-party dependencies are technical debt from day one
That convenient SDK that saves you two weeks of work? It's now a permanent fixture in your binary, a source of build warnings when they deprecate APIs, and a breaking change when they decide to rewrite their authentication flow. This is why 70% of developers prefer URLSession over third-party networking libraries. The native solution might be more verbose, but it won't break when a random startup pivots or closes its doors.

3. Authentication is never 'just authentication'
Every app in this analysis had authentication challenges. The OAuth flows themselves have documentation. The hard parts are handling partial credentials from Sign in with Apple, synchronizing auth state across CoreData, Firebase, and local caches, dealing with 503 errors from Apple's servers during peak times, implementing account deletion to comply with App Store requirements, and managing token refresh without breaking the user experience. Plan for auth to take 3x longer than your estimate.

4. Commit messages are documentation for future you
"Potential fix for unloaded code. Will need to continue to test and see" is a commit message from GoingVegan. Six months later, I came back to this code with a similar bug and had no idea what counted as "unloaded code." Good commit messages explain the reasoning as well as the change. They're breadcrumbs for when you inevitably return to long-forgotten code.

5. Product thinking matters more than technical perfection
PetSafe is the largest codebase at 13,000 lines, but it was built in four weeks. GoingVegan is smaller but took three years. The difference? PetSafe had a tight scope, clear user value, and ruthless prioritization. GoingVegan tried to be a complete vegan lifestyle platform from day one. The best product engineers know when to ship a focused v1 and when to build infrastructure for scale. The git history shows my evolution: early commits are feature-heavy, later commits are more surgical, more tested, more focused on user value.

Conclusion: product engineering as a practice
These three apps cover more than a decade of iOS development and trace the evolution from developer to product engineer. Writing better code helps, but the bigger shift is understanding that every technical decision has product implications. Choosing CocoaPods over SPM affects binary size, which affects download rates, which affects acquisition cost. Implementing authentication affects onboarding friction, which affects activation rates, which affects retention. Ignoring accessibility affects your addressable market.

The hardest challenges weren't in the code. They were the decisions about what to build, when to refactor, and when to ship with known issues. That's product engineering: the messy intersection of code, user needs, business constraints, and platform evolution.

If you're a product manager reading this, I hope you see that engineers who understand git history, dependency bloat, and authentication flows also understand user friction, technical debt, and trade-offs. If you're an engineer reading this, I hope you see that caring about these things adds to your effectiveness without subtracting from your technical depth.

The next 10 years will bring new frameworks, new paradigms, and new challenges. But the fundamentals remain: ship value, pay down debt, evolve with the platform, and leave the codebase better than its former self. One commit at a time.

Browse all guides