home / skills / rshankras / claude-code-apple-skills / migration-patterns

migration-patterns skill

/skills/ios/migration-patterns

This skill provides comprehensive migration guides for moving between Apple framework generations, outlining before/after mappings, coexistence strategies, and

npx playbooks add skill rshankras/claude-code-apple-skills --skill migration-patterns

Review the files below or copy the command above to add this skill to your agents.

Files (5)
SKILL.md
5.3 KB
---
name: migration-patterns
description: Migration guides for CoreData to SwiftData, UIKit to SwiftUI, ObservableObject to @Observable, and XCTest to Swift Testing. Use when migrating between Apple framework generations.
allowed-tools: [Read, Glob, Grep]
---

# Migration Patterns

Comprehensive guides for migrating between Apple framework generations. Each guide covers the full before/after mapping, coexistence strategies, and common pitfalls.

## When This Skill Activates

- User asks how to migrate from CoreData to SwiftData
- User is moving UIKit code to SwiftUI (or embedding one in the other)
- User needs to update from ObservableObject/Combine to @Observable/AsyncSequence
- User is converting XCTest tests to Swift Testing
- User asks about coexistence strategies (running old and new frameworks side by side)
- User wants to know whether a migration is worth doing for their situation
- User encounters errors during a framework migration

## Decision Tree

```
What are you migrating?
|
+-- Data persistence layer
|   +-- CoreData --> SwiftData
|   |   See coredata-to-swiftdata.md
|   |   Min: iOS 17 / macOS 14
|   |
|   +-- Still need CoreData features SwiftData lacks?
|       Stay on CoreData or use coexistence mode
|
+-- UI framework
|   +-- UIKit --> SwiftUI
|   |   See uikit-to-swiftui.md
|   |   Min: iOS 13 (basic), iOS 16+ (modern navigation)
|   |
|   +-- Full rewrite or incremental?
|       Incremental is almost always better -- adopt screen by screen
|
+-- State management / observation
|   +-- ObservableObject --> @Observable
|   |   See observable-migration.md
|   |   Min: iOS 17 / macOS 14
|   |
|   +-- Combine publishers --> AsyncSequence
|       Also covered in observable-migration.md
|
+-- Testing framework
    +-- XCTest --> Swift Testing
        See xctest-to-swift-testing.md
        Min: Xcode 16 / Swift 6.0
```

## Quick Reference

| Migration | Reference File | Minimum OS | Risk Level |
|-----------|---------------|------------|------------|
| CoreData to SwiftData | `coredata-to-swiftdata.md` | iOS 17 / macOS 14 | High (data layer) |
| UIKit to SwiftUI | `uikit-to-swiftui.md` | iOS 13+ | Medium (incremental) |
| ObservableObject to @Observable | `observable-migration.md` | iOS 17 / macOS 14 | Low-Medium |
| XCTest to Swift Testing | `xctest-to-swift-testing.md` | Xcode 16 | Low |

## Process

### 1. Assess the Migration

Before starting, determine:
- What is the minimum deployment target? Many migrations require iOS 17+.
- How large is the surface area? (number of models, screens, test files)
- Can you adopt incrementally or is it all-or-nothing?
- Are there third-party dependencies that assume the old framework?

### 2. Load Relevant Reference File

Based on the migration type, read from this directory:
- `coredata-to-swiftdata.md` -- NSManagedObject to @Model, migration stages, coexistence
- `uikit-to-swiftui.md` -- UIHostingController, Representable, incremental adoption
- `observable-migration.md` -- @Observable macro, @Environment injection, AsyncSequence
- `xctest-to-swift-testing.md` -- @Test, #expect, #require, parameterized tests

### 3. Review the User's Code

Scan for old-framework patterns and map each to its modern equivalent using the reference file. Check for:

- [ ] Deprecated API usage that has a direct modern replacement
- [ ] Custom workarounds that are no longer needed with the new framework
- [ ] Third-party dependencies that may conflict with the migration
- [ ] Coexistence requirements (both frameworks running simultaneously)

### 4. Recommend a Migration Strategy

For each migration, decide between:

- **Full migration**: Replace all old-framework code at once. Best for small codebases or when old framework is causing problems.
- **Incremental migration**: Migrate piece by piece while both frameworks coexist. Best for large codebases, production apps, or when timeline is flexible.
- **No migration**: The old framework is still appropriate. See "When NOT to Migrate" in each reference file.

## General Migration Principles

1. **Migrate tests first.** If you are migrating both app code and tests, migrate tests to Swift Testing first. This gives you a safety net for the app-code migration.

2. **One migration at a time.** Do not migrate CoreData to SwiftData and ObservableObject to @Observable in the same PR. Each migration should be independently reviewable and revertible.

3. **Keep the old code compiling.** During incremental migration, both old and new code must compile and run. Use coexistence patterns from each reference file.

4. **Feature-flag large migrations.** For production apps, consider gating new-framework code behind a feature flag so you can roll back without a code revert.

5. **Write migration tests.** For data-layer migrations (CoreData to SwiftData), write tests that verify data roundtrips correctly through both stacks.

## References

- [Migrating from CoreData to SwiftData](https://developer.apple.com/documentation/coredata/migrating-from-core-data-to-swiftdata)
- [Migrating to new navigation types](https://developer.apple.com/documentation/swiftui/migrating-to-new-navigation-types)
- [Migrating from ObservableObject to Observable](https://developer.apple.com/documentation/swiftui/migrating-from-the-observable-object-protocol-to-the-observable-macro)
- [Migrating a test from XCTest](https://developer.apple.com/documentation/testing/migratingfromxctest)

Overview

This skill provides practical migration guides for moving between Apple framework generations: CoreData to SwiftData, UIKit to SwiftUI, ObservableObject to @Observable, and XCTest to Swift Testing. It focuses on concrete before/after mappings, coexistence patterns, and common pitfalls so teams can plan safe, incremental migrations. Use it to assess risk, pick a strategy, and get migration-ready checklists.

How this skill works

Select the migration type and follow the decision tree that maps legacy APIs to modern equivalents. Each guide details minimum OS/Xcode requirements, coexistence strategies, and code-level patterns (e.g., NSManagedObject -> @Model, UIViewController -> UIHostingController/Representable). The skill inspects surface area (models, screens, tests), flags risky areas, and recommends full, incremental, or no-migration strategies.

When to use it

  • You’re upgrading a data layer from CoreData to SwiftData
  • You want to adopt SwiftUI but retain parts of UIKit
  • You’re moving from ObservableObject/Combine to @Observable/AsyncSequence
  • You need to convert XCTest suites to Swift Testing
  • You must run old and new frameworks side-by-side during rollout
  • You’re deciding if the migration ROI justifies the effort

Best practices

  • Migrate tests first to provide a safety net for app migrations
  • Perform one migration per PR to keep reviews focused and revertible
  • Keep both old and new code compiling during incremental adoption
  • Feature-flag large changes so you can rollback without a revert
  • Write migration tests for data-layer changes to verify roundtrips

Example use cases

  • Convert a single CoreData entity to @Model and validate coexistence with the remaining NSManagedObjects
  • Wrap an existing UIViewController with UIHostingController and migrate screens incrementally
  • Replace ObservableObject-based models with @Observable and switch Combine publishers to AsyncSequence stepwise
  • Port XCTest assertions to Swift Testing on Xcode 16 while keeping legacy tests running
  • Assess whether a small app should stay on CoreData because of missing SwiftData features

FAQ

What minimum OS or Xcode versions do migrations require?

Many migrations require iOS 17 / macOS 14 for SwiftData and @Observable; UIKit to SwiftUI works back to iOS 13 but benefits from newer APIs. Swift Testing needs Xcode 16 / Swift 6.

Should I migrate everything at once or incrementally?

Incremental migration is usually safer for production apps. Full migrations suit small codebases or when the old framework is actively blocking progress.