RORK LABEN
MAX — Rork MaxはClaude CodeとClaude Opus 4.6を基盤に、React NativeではなくネイティブSwiftアプリを直接生成しますAPPLE — Rork MaxはiPhone・iPad・Apple Watch・Apple TV・Vision Pro・iMessageまでAppleエコシステム全体を対象にしますWORKFLOW — 実運用ではAIに足場を作らせ、状態管理とデータ層は自分で書き直す分担に落ち着いてきたという声が目立ちますSEED — 4月にLeft Lane Capital主導で$15Mのシードを調達しました(Peak XV・True Ventures・a16z Speedrunが参加)PAPERLINE — アプリビルダーPaperlineを買収。エンジニア人材の獲得へ今後も買収を続ける方針ですREVIEW — 3ヶ月使ったユーザーの再訪レビューが増え、得意・不得意と向く用途の見極めが進んでいますMAX — Rork MaxはClaude CodeとClaude Opus 4.6を基盤に、React NativeではなくネイティブSwiftアプリを直接生成しますAPPLE — Rork MaxはiPhone・iPad・Apple Watch・Apple TV・Vision Pro・iMessageまでAppleエコシステム全体を対象にしますWORKFLOW — 実運用ではAIに足場を作らせ、状態管理とデータ層は自分で書き直す分担に落ち着いてきたという声が目立ちますSEED — 4月にLeft Lane Capital主導で$15Mのシードを調達しました(Peak XV・True Ventures・a16z Speedrunが参加)PAPERLINE — アプリビルダーPaperlineを買収。エンジニア人材の獲得へ今後も買収を続ける方針ですREVIEW — 3ヶ月使ったユーザーの再訪レビューが増え、得意・不得意と向く用途の見極めが進んでいます
記事一覧/開発ツール
開発ツール/2026-06-17上級

Rork Max の SwiftData をオフライン優先で同期する — 衝突を起こさない差分マージの設計

Rork Max が生成する SwiftData アプリを、電波が不安定でも編集を失わないオフライン優先で同期させる設計をまとめます。行ごとの上書きではなく変更を単位にした差分マージ、トゥームストーンによる削除の伝播、再送できる送信キューまで、本番で詰まった判断とともに実装で示します。

Rork Max223SwiftData2オフライン同期衝突解決差分マージアーキテクチャ16

プレミアム記事

iPad で壁紙のコレクションを並べ替えていた最中に地下鉄へ入ってしまい、改札を出てアプリを開き直したら並びが元に戻っていた——自分のアプリで、自分でそれを踏んだときの気まずさは忘れられません。保存は成功していたのに、オンラインに戻った瞬間にサーバー側の古い状態で上書きされていたのです。

Rork Max が生成するのはネイティブの Swift アプリなので、ローカルの保存は SwiftData で素直に書けます。けれど「ローカルに保存できた」と「同期しても消えない」は別物です。ここでは、電波が不安定でも編集を失わないオフライン優先の同期を、行の上書きではなく差分のマージとして組む設計を整理します。

「保存できた」がなぜ信用できないのか

多くの同期実装は、端末の現在状態をまるごとサーバーへ送り、サーバーの状態をまるごと端末へ書き戻します。これは片方向で一台しか触らない間は動きますが、二台目が現れた瞬間に壊れます。iPhone で付けたお気に入りと、iPad で変えた並び順が、後から同期したほうの「全体」で互いを潰し合うからです。

問題の本質は、同期の単位を「行(レコードの最終状態)」に置いていることにあります。最終状態だけを見ると、どちらが新しいかしか判定できません。実際に必要なのは「誰が・いつ・どのフィールドを変えたか」という変更の履歴です。単位を行から変更へ移すと、別々のフィールドへの編集は衝突せずに共存できます。

SwiftData モデルに同期メタデータを持たせる

まず、各モデルへ同期判断に使うメタデータを足します。更新時刻、論理削除フラグ(トゥームストーン)、そして同期済みかどうかを表すローカル専用の状態です。

import SwiftData
import Foundation
 
@Model
final class WallpaperItem {
    @Attribute(.unique) var id: UUID
    var title: String
    var sortIndex: Int
    var isFavorite: Bool
 
    // --- 同期メタデータ ---
    var updatedAt: Date          // 最後に「中身」を変えた時刻
    var isDeleted: Bool          // トゥームストーン(物理削除しない)
    var dirty: Bool              // ローカルの未送信変更があるか
    var revision: Int            // サーバーが採番する版番号
 
    init(id: UUID = UUID(), title: String, sortIndex: Int) {
        self.id = id
        self.title = title
        self.sortIndex = sortIndex
        self.isFavorite = false
        self.updatedAt = .now
        self.isDeleted = false
        self.dirty = true
        self.revision = 0
    }
}

ポイントは三つあります。id をサーバーと共有する UUID にして端末をまたいで同一性を保つこと。削除を isDeleted の論理削除にして、消えた事実そのものを同期できるようにすること。そして dirty で未送信の編集を覚えておき、電波が戻った時に何を送ればよいかを端末側が把握できるようにすることです。

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
SwiftData モデルに同期メタデータを持たせ、最後の書き込みだけで上書きしない差分マージの実装が手に入る
削除を「行を消す」ではなくトゥームストーンで伝播させ、片方の端末で復活してしまう事故を防ぐ設計が分かる
電波が切れても編集を捨てない送信キュー(アウトボックス)の作り方と、二重送信を避ける冪等キーの置き方が分かる
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

開発ツール2026-06-22
無印 Rork と Rork Max を1つのバックエンドで支える — 旧バイナリを壊さない API レスポンス契約の設計
無印 Rork(React Native / Expo)と Rork Max(ネイティブ Swift)が同じ Cloudflare Workers バックエンドを叩く構成では、強制アップデートできない旧バイナリを壊さないことが設計の中心になります。レスポンスを封筒型にして加算のみで育て、能力フラグでクライアント差を吸収し、古いバージョンを安全に畳むまでを実装で示します。
開発ツール2026-06-16
Rork Max のネイティブアプリで CloudKit 同期を設計する — 競合と削除をどう扱うか
iPhone と iPad で同じデータを同期させたい——Rork Max が生成した Swift アプリに CloudKit を入れる際、本当に難しいのは保存ではなく『競合』と『削除』の扱いでした。実装で固めた設計判断を整理します。
開発ツール2026-06-16
Rork Max が生成した SwiftUI アプリに SwiftData を後付けする
Rork Max が出力した SwiftUI コードは画面は作れても永続化が @State 止まりになりがちです。SwiftData を後付けする際のモデル設計、ContainerとViewの接続、スキーマ移行の実装パターンを手を動かしながら整理しました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →