Skip to main content

Your First Freeze

This tutorial walks you through freezing your first SwiftData schema with FreezeRay, from installation to verifying drift detection works. Time required: 10-15 minutes What you’ll learn:
  • Install FreezeRay CLI and package
  • Add @FreezeSchema to your schema
  • Freeze a schema version
  • Run drift detection tests
  • Commit fixtures to git

Prerequisites

Before starting, ensure you have:
  • Xcode 15.0+ installed
  • macOS 14+
  • An iOS 17+ app with SwiftData
  • Git for version control
  • npm (for CLI installation)
  • Your project uses VersionedSchema (not just plain Schema)
If your app doesn’t use VersionedSchema yet, you’ll need to migrate to it first. See Apple’s SwiftData migration documentation.

Step 1: Install FreezeRay CLI

Install the CLI via npm:
Verify installation:
Apple Silicon users: The CLI includes pre-built binaries.Intel Mac users: The CLI will build from source automatically (requires Swift toolchain).

Step 2: Initialize FreezeRay in Your Project

Navigate to your Xcode project directory:
Run the init command:
What this does:
  • Creates FreezeRay/Fixtures/ and FreezeRay/Tests/ directories
  • Adds FreezeRay Swift package to your project
  • Updates your Xcode project or Package.swift
Expected output:

Step 3: Update Your Schema Definition

Open your schema file (e.g., Schemas.swift or DataModel.swift) and import FreezeRay:
Add @FreezeSchema to your schema:
The @FreezeSchema(version:) string (“1.0.0”) is separate from SwiftData’s versionIdentifier. Use it to organize your fixtures.
If you have multiple schema versions, annotate each:

Step 4: Build Your Project

Before freezing, ensure your project builds:
If your project doesn’t build, the freeze command will fail. Fix any build errors before continuing.

Step 5: Freeze Your Schema

Now freeze your schema version:
What happens:
  1. Auto-detection - Discovers project, scheme, and test target
  2. Source parsing - Finds @FreezeSchema(version: "1.0.0") in your code
  3. Test generation - Creates temporary test file
  4. Simulator run - Builds and runs in iOS Simulator
  5. Fixture extraction - Copies SQLite database from simulator
  6. Test scaffolding - Generates drift detection test
Expected output:
The freeze process takes 30-60 seconds depending on your project’s build time.

Step 6: Inspect the Fixtures

Check what was created:
Output:

Examine the SQLite database

You’ll see SwiftData’s internal schema:
This is the actual schema SwiftData created - not a theoretical representation.

Check the drift test

Open FreezeRay/Tests/AppSchemaV1_1_0_0_DriftTests.swift:
This test runs on every test execution and verifies your schema hasn’t changed.

Step 7: Run Tests

Run your test suite to verify drift detection works:
Or in Xcode: ⌘U Expected result: All tests pass, including the new drift test.
The drift test should always pass immediately after freezing. If it fails, something went wrong during the freeze process.

Step 8: Verify Drift Detection Works

Let’s test that drift detection catches schema changes:
  1. Modify your frozen schema (temporarily):
  2. Run tests again:
  3. Observe the error:
  4. Revert the change:
  5. Tests pass again:
Success! Drift detection is working.

Step 9: Commit to Git

Commit the fixtures and tests to version control:
Always commit fixtures immediately after freezing. They must be in git for:
  • CI/CD to run drift tests
  • Team members to have the same fixtures
  • Traceability (which commit introduced the schema)

Step 10: Team Workflow

When other developers pull your changes:
They automatically get:
  • The frozen fixtures (FreezeRay/Fixtures/1.0.0/)
  • The drift test (FreezeRay/Tests/AppSchemaV1_1_0_0_DriftTests.swift)
When they run tests (⌘U), drift detection verifies they haven’t accidentally modified the frozen schema.

What’s Next?

You’ve successfully frozen your first schema! Here’s what to do next:

Add a Second Schema Version

When you need to make schema changes:
  1. Create a new schema version:
  2. Generate migration test:
    This creates MigrateV1_0_0toV2_0_0_Tests.swift. Edit it to add custom data validation.
  3. Add migration:
  4. Develop and test: Run tests (⌘U) as you implement the schema and migration.
  5. Freeze the new version:
    This generates fixtures and drift test only. The migration test already exists from step 2.

Set Up CI Integration

Add FreezeRay to your CI pipeline to catch drift on every PR:
See the CI Integration guide for full setup.

Customize Tests

Add custom validation to drift and migration tests:
See the Testing Migrations guide for examples.

Troubleshooting

”No @Freeze(version: “1.0.0”) annotation found”

Problem: You forgot to add @FreezeSchema to your schema. Solution:

“Build failed”

Problem: Your project doesn’t compile. Solution: Fix build errors in Xcode (⌘B) before running freezeray freeze.

”Test failed”

Problem: Your existing tests are failing. Solution: Fix failing tests before freezing. The freeze command requires all tests to pass.

”Simulator not found: iPhone 17”

Problem: You don’t have iPhone 17 simulator installed. Solution: Option 1 - Install iPhone 17 simulator:
Option 2 - Use a different simulator:

Drift test fails immediately after freezing

Problem: Something went wrong during the freeze. Solution:
  1. Delete fixtures: rm -rf FreezeRay/Fixtures/1.0.0/
  2. Freeze again: freezeray freeze 1.0.0
  3. If it still fails, file a bug report at github.com/TrinsicVentures/FreezeRayCLI/issues

Summary

You’ve learned how to:
  • ✅ Install FreezeRay CLI and initialize your project
  • ✅ Annotate schemas with @FreezeSchema(version:)
  • ✅ Freeze a schema version to create immutable fixtures
  • ✅ Run drift detection tests
  • ✅ Commit fixtures to version control
Your schema is now frozen and protected from accidental changes!

Next Steps

Migration Testing

Learn how to test migrations between schema versions

CI Integration

Set up drift detection in your CI pipeline

Schema Freezing Concepts

Deep dive into how schema freezing works

Drift Detection Concepts

Understand how checksums catch schema changes