RORK LABJP
SDK58 — The Expo SDK 58 beta is open. It ships the React Native 0.88 release candidate, and the beta period is stated as three to four weeks11/01 — For anyone who requested an extension, Google Play's target API deadline lands on November 1. Forty-four days outEASENV — A long-open report: secrets handed to a local build arrive as the literal variable name rather than its value, and the damage surfaces much laterNEW — The replacement the table recommended had already shut down. A record of reconciling all 74 rows of the deprecation listUISCENE — iOS 27 requires the new scene lifecycle. SDK 57 makes it something you opt into; it only becomes the default in 58CREDIT — What "AI errors don't cost credits" actually covers becomes clear once you record a day of asking for the same fix more than onceSDK58 — The Expo SDK 58 beta is open. It ships the React Native 0.88 release candidate, and the beta period is stated as three to four weeks11/01 — For anyone who requested an extension, Google Play's target API deadline lands on November 1. Forty-four days outEASENV — A long-open report: secrets handed to a local build arrive as the literal variable name rather than its value, and the damage surfaces much laterNEW — The replacement the table recommended had already shut down. A record of reconciling all 74 rows of the deprecation listUISCENE — iOS 27 requires the new scene lifecycle. SDK 57 makes it something you opt into; it only becomes the default in 58CREDIT — What "AI errors don't cost credits" actually covers becomes clear once you record a day of asking for the same fix more than once
Articles/Dev Tools
Dev Tools/2026-06-16Advanced

Adding SwiftData to a SwiftUI App Generated by Rork Max

Rork Max can produce polished SwiftUI screens, but persistence often stops at @State. Here is how I layer SwiftData onto generated code: model design, wiring the container to views, and a schema migration pattern that survives shipping.

Rork Max234SwiftData2SwiftUI65PersistenceMigration2

Premium Article

One evening I was looking at the SwiftUI code Rork Max gave me after I asked it to "build a habit tracker," and my hand froze on the trackpad. The screens were more thoughtful than I expected — the list, the checkboxes, all neatly laid out. But every time I relaunched the app, every habit I had entered was gone.

The reason was obvious the moment I opened the source. The data lived only in @State private var habits: [Habit] = [], never written to disk at all. Rork Max is excellent at producing a screen that looks like it works as fast as possible, but it does not design the persistence layer for you. That was the lesson of the night.

In this article I want to record the full path of taking that generated code and growing it into an app that survives a relaunch, with the actual code I wrote. I am assuming iOS 17 or later and that you can open the SwiftUI Rork Max emits in Xcode or a cloud build.

Why staying on @State eventually breaks

Freshly generated code usually looks like this.

struct Habit: Identifiable {
    let id = UUID()
    var name: String
    var doneToday: Bool
}
 
struct ContentView: View {
    @State private var habits: [Habit] = [
        Habit(name: "Morning walk", doneToday: false),
        Habit(name: "Reading", doneToday: false)
    ]
 
    var body: some View {
        List($habits) { $habit in
            Toggle(habit.name, isOn: $habit.doneToday)
        }
    }
}

As a screen, this is finished. But @State is in-memory state tied to the lifetime of the view, so it disappears when the process ends. Good enough for a demo, not viable for an app people open every day.

Many of us reach for serializing a Codable into UserDefaults as JSON next. I did exactly that in my early apps. The trouble is that once items grow and you need relationships or query conditions, reading and writing the whole JSON blob gets painful fast. SwiftData is designed for data that grows, so as an indie developer I have found that spending a little effort up front to move onto it pays off later.

Step 1: Replace the struct with @Model

The first move is turning the struct into an @Model class. The catch is that it becomes a final class rather than a struct — miss that and it will not compile.

import SwiftData
 
@Model
final class Habit {
    var name: String
    var doneToday: Bool
    var createdAt: Date
 
    init(name: String, doneToday: Bool = false, createdAt: Date = .now) {
        self.name = name
        self.doneToday = doneToday
        self.createdAt = createdAt
    }
}

Once @Model is applied, SwiftData tracks property changes automatically and treats the object as something to persist. You do not need to hold an id by hand; SwiftData manages an internal persistent identifier.

There is a judgment call here. If the generated code still has let id = UUID(), you can drop it as long as your views and animations do not depend on it. But if a ForEach references it via id:, I prefer to keep an explicit UUID property as a stable identifier. Rork Max output tends to be ambiguous here, so it is safest to check how ForEach is used before deciding.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
A step-by-step path from @State-only generated code to SwiftData @Model storage
VersionedSchema and MigrationPlan code that lets your schema grow without breaking the app
A ModelContainer fallback design that keeps the app launching even when migration fails
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $15 for lifetime access
View Membership →

Related Articles

Dev Tools2026-07-18
The Generated Screen That Quietly Jams at AX5 and in German — Putting Layout Resilience Checks on Rork Max SwiftUI
A record of running every Rork Max generated SwiftUI screen through pseudolocalization and the largest text size to find exactly where it jams. Covers when to reach for ViewThatFits, ScaledMetric and layoutPriority, plus the snapshot checks that catch regressions every time you regenerate.
Dev Tools2026-07-12
A symbolEffect Field Memo: Making Icons Move Nicely in Your Rork Max App
Animate SF Symbols in a Swift app generated by Rork Max using bounce, pulse, variableColor, and contentTransition, with working code, OS-version gating, and the mistakes I made from over-animating.
Dev Tools2026-07-09
Getting Rork Max's Swift Through Swift 6's Strict Concurrency Checking
A field record of taking a Rork Max-generated SwiftUI app through Swift 6 complete concurrency checking: 217 warnings cleared target by target, where @MainActor actually belongs, and measured before/after numbers.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links