Reviewing AI-generated Code for iOS

Nov 5 2026 · Swift 5, iOS 27, Xcode 27

Lesson 02: Using AI to Improve the Review

Using AI to Improve the Review

Episode complete

Play next episode

Next

Written by the author, AI-editedAI-generated, author-verified How this module was made

Transcript

In the last lesson, I reviewed the Tokens Dashboard app manually and found three things worth fixing. The starter project here is the same app before any of those fixes. That’s intentional because we want the AI reviewing the exact same code, so the comparison means something. I’m going to run two prompts.

First one, completely open with no guidance. Second one has the same seven-category checklist I used by hand.

I’m doing this using Claude directly inside Xcode under the Intelligence panel. If you have followed along from module one, this should already be set up. Claude already has full project context. No pasting code, no switching app.

And now let’s run the first prompt.

Review this codebase the way a senior iOS engineer would in a pull request. Point out anything you'd flag before approving. Don't just describe what the code does.

Okay, let’s look at what came back.

Before I walk through this, the output you see on my screen right now will probably look different from yours. That’s expected with AI. The findings may vary, the wording will be different, and that’s completely fine. What matters here is the process, not the exact output.

Something worth noting before we get into specifics here, Claude organized these into its own categories. You see crash definite bugs, silent logic bugs, visual bugs, architecture issues, cleanup, and maintenance. I didn’t ask for that structure. Yours might come back totally different. That’s fine.

Now, from what I found manually in lesson one, let’s check. For example, here in back two, item two here, the force unwrap dates in two file, it’s the same finding. Which confirmed. Good.

If we scroll up to item one, you will see something that I didn’t catch, the app title, Tokens Dashboard Summary with a possessive apostrophe on screen for every launch, but we didn’t notice it yet. It’s an easy fix that we can do.

Also this one, I missed this one completely. Two parallel arrays with no boundary check. If they ever have different lengths, the app crashes at startup. That’s a real crash risk I wouldn’t have found on a quick read.

There are many items below, architecture, cleanup, maintenance. I’m not going to go through all of them here because the next prompt is where we get structured and detailed. Going category by category. That’s when the real comparison happens. Now let’s run the second prompt.

Review this project as a senior ios engineer would in a pull request, checking specifically against each of these categories: correctness, architecture, performance,  security, accessibility, testing, and maintainability. Go through the categories one at a time and tell me what you find in each, including saying "nothing notable" for categories where there isn't an issue.

Same app, same AI, different prompt. This time it follows my order, starting with correctness.

The force unwrap is here. We already saw this in the first prompt, and I caught it manually in lesson one. Three passes, same finding. That’s about as clear as it gets.

The parallel array crash risk came up in the first prompt too. For the asymmetric median boundary, it’s also in first prompt, but it was filed under logic bug there. Here, it’s correctness, same problem, different label. The checklist changes how findings get classified, not just what gets found. The typo also here as the first prompt.

For architecture, destination graph declared inside a view file but used by the view model. The dependency is pointing the wrong direction. That’s a real layering issue.

In summary view model, summary view model calling ticket to merge view models formatting method, and that is duplicated logic I found manually in lesson one, but framed more precisely here. A formatting helper sitting on the wrong type.

The main entry point collected with content view, and this is new. Two responsibilities in one file which can easily separate it. We have no dependency injection on the stores, and this is also a new finding. With deeper refactoring, we can solve it, but we will leave it for now.

In performance, nothing notable, and that’s actually a good result, not a gap. For a simple local app like this one with fixed in-memory data and no network calls, there is nothing here that should be a performance concern. The checklist covers the category, it came up clean, and we move on. That’s exactly what we want to see.

Same here for security. Nothing notable, no networking, no user input, no credential anywhere in the project. For an app this simple, this is the right answer. Security is covered. It’s good to go. This is worth pointing out because a reviewer who tries to find something in every category, even when there is nothing wrong, produces noise, not value. Nothing notable is a legitimate, useful finding. Both correct answers for a local static data app.

For accessibility, this section didn’t exist at all in the first prompt. The scatter chart here has no whole chart summary label for VoiceOver. Users can navigate dot by dot but get no overview. The line chart in the same app handles this correctly. The scatter chart doesn’t.

Needs coaching is shown by color only. Orange versus indigo. No shape difference, no alternative signal. Users with color blindness get nothing. Again, the line chart already does this right with symbol shapes. The scatter chart should match.

In lesson one, the accessibility looked solid. This structured pass just found two real gaps. On a screen I thought it was already fine. That’s the difference between a quick impression and a category-by-category pass.

For testing, no tests at all. The CLAUDE.md even says to use this testing framework, but nothing exists. This is noted, but this is out of our scope for this module.

Finally, the maintainability. The naming inconsistency across files you can see here. The naming inconsistency between cost by model and cost by model view model is confirmed again. And there is a stray caution here. You can see this comment sitting in the middle of summary view, a sign the file was assembled from fragments and never cleaned up.

Now we have two prompts, same app. The first one found real things but went where it happened to look. This one covered all seven categories, and the accessibility section alone found things I missed on a screen I thought was already done right. That’s not AI getting smarter. It’s structured attention finding what unfocused attention mentioned.

One more prompt, which of these are real bugs and which are just style preferences? Then we will apply these fixes.

This is exactly what I needed. It’s gone through each category and made a clear call on each finding.

For correctness, most of its findings came back as real crash risks or real bugs. The force unwraps, the parallel arrays, the typo, all real bugs.

For architecture, it’s interesting because the destination graph layering issue and the cross-view model dependency are both flagged as real bugs. But the main collected with content view and the missing dependency injection are style preferences. Same category, very different severity.

For testing, it came back as a real bug because the CLAUDE.md explicitly requires tests and none exist. I’m noting that, but it’s still out of scope for this module, regardless of how it’s classified.

The naming inconsistency, it’s a style preference. The stray AI caution comment, style preference. Those stay.

Now we have a clear list. Let’s apply it.

Fix everything you just classified as a real bug or crash risk. Leave everything classified as a style preference untouched. Also leave the testing gap as-is. That's out of scope here. Show me every file you plan to change before applying anything.

Now we have the results. Let me read through this before saying yes. This is exactly why I asked it to show me the plan first. I want to see what it’s going to touch before anything changes. As you see, models, view models, views, all three layers. The change looks right. However, this is interesting seeing it move destination graph from the view file to summary view model as part of fixing the layering issue. It understood the actual fix, not just the surface problem.

Here are all the changes applied. On the right, you can see the changes for each one. Take a moment to scroll through and do a final check before building. Finally, notice this summary for all the changes happened. Everything looks right. Now let’s build and run. Now let’s go through the app to make sure that all screens are working as expected. Now everything is good. We are done here.

Some things we didn’t touch today, the style preferences, the testing gap, and the naming inconsistency. Not because they don’t matter, but because a review that tries to fix everything at once fixes nothing well.

In the next lesson, we make sure these standards carry forward, so the next time AI writes code for this project, it already knows what we care about.

See forum comments
Cinema mode Download course materials from Github
Previous: Introduction Next: Conclusion