I Built a Real iOS App with AI. Here's the Honest Truth
The Good, The Bad, and The Code I Had to Write Myself
Everyone’s got an opinion on AI in software development. Half the internet wants to tell you it’s going to replace developers. The other half is convinced it’s an overhyped toy that writes garbage code and calls it a day. The truth? It’s somewhere in the middle. And most people writing about it have never actually shipped anything with it.
I have. I built a real, live iOS app using Claude Code as my primary coding partner. It’s in the App Store right now. And I’m here to tell you it was both more impressive and more frustrating than I expected.
The Project: Svngs+
I work as a software engineer in fintech, dealing with legacy loan origination and servicing platforms all day. Heavy C#, TypeScript, SQL. Complex problems. I genuinely love it. There’s nothing quite like getting lost in a mind-bending problem and finally having that “aha” moment.
Best part of the job.
But spending that much time in financial systems got me thinking about my own finances. I wanted a simple way to track my savings rate, just log your net income and how much you saved each pay period. That’s it. No fancy dashboards, no bank integrations, no giving a third-party app access to your financial life.
So I built Svngs+. A native iOS app. Privacy-first. No third-party APIs, no cloud storage I control. Your data lives in Apple’s CloudKit, only you can see it. And I used this as the perfect opportunity to push Claude Code and see what it could actually do on a real project, not just a throwaway demo.
The Decision That Made Everything Else Work
Before writing a single line of code, I made one call that I think saved the whole project: I decided to use Claude as a pair programmer, not a full agentic solution.
This might sound like a small distinction. It’s not.
Going fully agentic means handing over the wheel. Let the AI run, generate, commit, and iterate on its own. Some people swear by it. My take? That’s a great way to end up with a codebase that works until it suddenly, catastrophically doesn’t. I wanted to review every piece of code Claude generated in real time. I managed the git workflow myself. I stayed in the driver’s seat.
That decision shaped everything about how the build went, including knowing when to trust the output and when to throw it out and do it myself.
The Framework: Four Parts Before You Write Any Code
One thing I’d recommend to anyone trying this workflow: don’t just fire up Claude Code and start asking it to build things. You’ll get slop. I broke the project into four phases before touching the IDE.
Part 1: Product Definition. What does this app do, what problem does it solve, who’s it for? Nothing technical yet. Just the idea, the scope, and a rough version breakdown so I could define a real MVP.
Part 2: User Flow. Every screen, every interaction, the full onboarding experience. Map it out before you build it.
Part 3: Tech Spec. This is where the nuts and bolts live. Architecture decisions, dependencies, data layer. For Svngs+, that meant Swift, SwiftUI, SwiftData for local storage, CloudKit for cross-device sync, StoreKit for an in-app purchase that unlocks unlimited history, and biometric authentication via Face ID, Touch ID, or passcode.
Part 4: Build Plan. This is the heart of working with Claude Code. Break the MVP into phases, break those phases into hyper-focused tasks. Every task is its own session. I also generated a CLAUDE.md file that set up ground rules: patterns to follow, where code should live, what to avoid.
That structure kept Claude on track. Without it, you’re just prompting into the void.
Where Claude Actually Impressed Me
Five weekends. One App Store submission. Let’s give credit where it’s due.
Claude was genuinely strong with Swift. Modern Swift, not legacy Objective-C patterns dressed up in new syntax. Best practices around SwiftUI were solid. The component structure it generated was clean, readable, and maintainable. For a lot of the standard UI work and business logic, I was reviewing code and thinking “yeah, I’d have written it pretty much like this.”
The in-app purchase flow with StoreKit? Handled it well. Local notifications for reminders? Clean. The biometric authentication setup? Worked first time.
When Claude was in its lane, building against well-documented, modern Apple frameworks, it was a legitimately good pair programmer. Fast, consistent, and it didn’t complain when I told it to redo something.
Where It Fell Apart
Here’s the part that doesn’t make it into most of these “I used AI to build an app” posts. Because there were real failures, and they’re worth talking about.
The SwiftData / CoreData confusion.
SwiftData is Apple’s modern ORM framework. CoreData is the older one SwiftData is built on. They’re related but they are not the same thing, and Claude kept reaching for CoreData patterns when it should have been thinking in SwiftData. Early sessions I was catching these before they caused problems. But it was a consistent friction point that required me to course-correct repeatedly. If I hadn’t known the difference, if I’d been a less experienced developer leaning on AI to fill knowledge gaps, this would have quietly poisoned the codebase.
The CloudKit disaster.
This one’s the best example of why you cannot go fully agentic and walk away.
CloudKit sync through SwiftData is largely automatic. Apple built it that way. You configure the container correctly, and it just works. There’s no custom sync model to write. Claude did not believe this. It kept trying to build me a sync manager, custom code to handle something the framework already handles natively. I kept redirecting it. It kept reverting.
Eventually I had to configure the CloudKit container myself, following Apple’s own documentation. Here’s the kicker: Claude found that documentation. It surfaced the right Apple dev docs during our session. Then apparently decided the docs were optional and did its own thing anyway. I ended up coding that piece entirely by hand.
The AI found the correct answer and ignored it. Without my experience to recognize the problem and my willingness to step in, that feature would have shipped broken or over-engineered. And I might not have even known why.
The StoreKit abstraction it ignored.
Before building the in-app purchase flow, I had a decision to make: StoreKit directly, or RevenueCat. For the MVP I kept it simple and went with StoreKit, but I wanted the flexibility to swap in RevenueCat later if I add subscriptions down the road. The right move in Swift is to define a protocol that the rest of the app talks to, then inject whichever implementation you’re using. Clean, future-proof, easy to swap.
Claude built the protocol correctly. Built the StoreKit class correctly. Then went ahead and injected StoreKit directly throughout the app, completely bypassing the abstraction it had just created. It did the hard part right and then ignored it. I caught it, fixed the injection, and now the app talks to the protocol the way it should. But if I hadn’t been reviewing in real time, I’d have a codebase that works today and becomes a pain in the ass the moment I want to make a change.
The fastlane screenshot setup.
Minor compared to the others, but Claude had real trouble with seed data for automated App Store screenshot generation. I got it across the line myself, but it took longer than it should have.
The Honest Take
Here’s where I land after five weekends and one App Store submission: AI is a legitimately powerful tool in the right hands. But “in the right hands” is doing a lot of work in that sentence.
You still need to know what good code looks like. You still need to know when to trust the output and when to throw it in the trash. The slop code problem is real. It might not bite you today, but it will eventually. Technical debt is sneaky like that. You feel fine right up until you don’t.
Think of it like a junior dev who’s brilliant half the time and confidently wrong the other half. You wouldn’t let that person commit without review. Same rules apply here.
Use AI as a pair programmer. Own the architecture. Review everything. And maybe don’t let it anywhere near your CloudKit configuration.
Svngs+ is live in the App Store if you want to check it out. I’m already working on the next app using the same workflow and refining the process as I go.
I’m curious where you’re at with AI in your own dev work. Are you using it as a pair programmer, or have you gone full agentic? And if you’ve been burned by slop code making it to production, I’d love to hear that story, drop it in the comments.
👉 If you enjoy reading this post, feel free to share it with friends!
Or feel free to click the ❤️ button on this post so more people can discover it on Substack 🙏
You can find me on X and Instagram.
Also, I just launched a new YouTube channel - Code & Composure


