title: migrating cartola fc with claude subtitle: how ai-assisted refactoring compressed months of objective-c into weeks of swift date: "2026" readingTime: "8 min" order: 1
context
cartola fc is one of the most-used apps in brazil. football, fantasy, millions of users, traffic that triples on sundays. like most apps with a decade of history, parts of it were still in objective-c with uikit. the team had wanted to migrate for years; the calendar always pushed it back.
i owned a large area of that legacy code. the conventional path would take months. i tried something different and it took weeks.
this is how.
the problem
the code was a mix of massive view controllers, direct networking calls inside view lifecycle methods, and model objects that were half-objc half-swift already. every time someone estimated the migration, the number came back in months — too long to justify when there were features waiting.
why a strangler pattern
a big-bang rewrite would have meant freezing feature work for months on an app that ships updates weekly during the football season. that was never going to happen.
the strangler pattern lets you replace legacy code incrementally. old objc screens coexist with new swift screens. users never notice the transition. the app stays shippable at every commit.
the trade-off: you carry the complexity of two systems for a while. bridging objc and swift isn't free — especially around runtime behaviors, optionality differences, and threading models. but for an app where downtime costs real users during live matches, incremental was the only responsible path.
where claude fit in
this is the part people ask about.
i used claude (anthropic) as the primary ai tool for the migration. not as a "write my code" button — as a force multiplier for the mechanical parts of the work.
context loading
claude's long context window was the key enabler. i could feed it an entire objective-c view controller — 800, 1200 lines — along with its associated models and networking code. claude could hold the full picture of a feature area, not just a single file.
what claude generated well
→ swift syntax from objc patterns — the mechanical translation of method signatures, property declarations, enum definitions
→ swiftui views from uikit view controllers — layout structure, data flow, basic state management
→ boilerplate — codable conformances, test scaffolding, mock objects
→ repetitive transformations — when 15 screens followed the same pattern, claude was consistent in a way that manual work wouldn't be at 2am
what claude got wrong
→ architectural decisions: claude would generate code that looked clean in isolation but didn't fit the existing module structure or dependency graph
→ outdated apis: defaulting to pre-ios 17 patterns when we could target newer apis
→ objc runtime edge cases: subtle behaviors around nil messaging, dynamic dispatch, and kvo that the swift version needed to handle explicitly
→ state management: claude's generated swiftui state management was often too simplistic for screens with complex data flows
the review loop
every generated file went through manual review. no exceptions.
what i always checked: → state management and data flow → threading boundaries (async/await, mainactor) → objc interop edge cases → accessibility labels and traits → the test suite (existing + new snapshot tests)
prompting strategy
what shipped
the migration completed in under a month. the conventional estimate was several months.
the migrated code is now in production, serving millions of users every match day.
what i'd do differently
→ establish a strict prompt template earlier — i spent the first week iterating on how to feed context to claude, which could have been a day-one decision
→ invest more in automated diff validation between old and new output — manual comparison doesn't scale and i caught at least two regressions late
the lesson
ai-assisted migration works when the engineer understands both the source and target deeply enough to review every line. the speed didn't come from skipping decisions — it came from compressing the mechanical work between decisions.
claude didn't know the codebase. i did. that's the difference between using ai as a tool and using it as a replacement.
by escaleira / 2026