Skip to content

Update Swift Quickstart for Ditto v5 + Swift 6 / strict-concurrency readiness #236

Merged
Aaron LaBeau (biozal) merged 15 commits intomainfrom
da-138-update-v5-swift
May 5, 2026
Merged

Update Swift Quickstart for Ditto v5 + Swift 6 / strict-concurrency readiness #236
Aaron LaBeau (biozal) merged 15 commits intomainfrom
da-138-update-v5-swift

Conversation

@biozal
Copy link
Copy Markdown
Contributor

@biozal Aaron LaBeau (biozal) commented Jan 31, 2026

This PR migrates the Swift quickstart from Ditto SDK 4.14.3 → 5.0.0 and brings the sample up to Swift 6 / strict-concurrency standards.

1. SDK migration (DittoSwift 4.x → 5.0.0)

Initialization — sync init → async Ditto.open

The v4 synchronous identity-based initializer is gone. v5 introduces an async config-based open.

Before (v4) After (v5)
Ditto(identity: .onlinePlayground(appID:token:enableDittoCloudSync:customAuthURL:)) try await Ditto.open(config: DittoConfig(databaseID:connect: .server(url:)))
appID databaseID
customAuthURL connect: .server(url:)
enableDittoCloudSync: false (removed — implicit)
transportConfig.connect.webSocketURLs.insert(...) (removed — Auth URL is canonical)
try ditto.disableSyncWithV3() (removed — v5 only)

Token refresh now uses auth.expirationHandler + auth.login

DittoManager.initDitto() registers an expiration handler that re-authenticates with auth.login(token:provider: .development) when the token nears expiry.

Sync API namespacing

Before After
ditto.startSync() ditto.sync.start()
ditto.stopSync() ditto.sync.stop()
ditto.isSyncActive ditto.sync.isActive

DQL strict mode bootstrap removed

v5 no longer requires ALTER SYSTEM SET DQL_STRICT_MODE = false for unfielded SELECTs against the quickstart schema, so TasksApp.task now just calls
DittoManager.shared.initDitto().

Package dependency

  • DittoSwiftPackage bumped to 5.0.0 (upToNextMinor).
  • DittoObjC product dependency dropped — DittoSwift now ships its ObjC bridge internally.

2. Concurrency / Swift 6 strict-concurrency

The PR-review feedback flagged a real data-race bug in the initial v5 port (@Published ditto mutated from a non-MainActor continuation). Audit found and fixed several related
issues so the sample is Swift 6 strict-concurrency clean and a faithful reference for SDK consumers.

# Issue Fix
1 DittoManager not @MainActorself.ditto = ... after await Ditto.open(...) could resume off-main and publish from a background thread. Annotated @MainActor on DittoManager.
2 EditScreenViewModel not @MainActor despite owning four @Published properties. Annotated @MainActor.
3 Five Task {} blocks in TasksListScreenViewModel captured self strongly; four were on nonisolated methods — Swift 6 sending self errors and unbounded VM lifetime. All five blocks now [weak self] + guard let self; nonisolated removed from saveEditedTask, saveNewTask, deleteTask, populateTasksCollection (all are called only from @MainActor SwiftUI contexts).
4 deinit accessed @MainActor-isolated subscription, storeObserver, dittodeinit is always nonisolated, so this was a Swift 6 isolation violation. Cleanup moved into @MainActor func teardown(), invoked from .onDisappear.
5 private let ditto = DittoManager.shared.ditto captured the optional at init time — if the VM ever initialized before initDitto() finished it would silently capture nil forever. Replaced with private var ditto: Ditto? { DittoManager.shared.ditto } (computed).
6 TaskModel had only implicit Sendable synthesis despite crossing actor boundaries. Explicit struct TaskModel: Sendable.
7 Stale UserDefaults.standard.synchronize() call (no-op since iOS 12). Removed.

Observer callback was already correct

The DittoStoreObserver callback in init() already hops back to MainActor via Task { @MainActor [weak self] in self?.tasks = mappedTasks } — preserved unchanged.

3. Project / housekeeping

  • LastUpgradeCheck bumped (16102620).
  • Dev team setting removed for cross-account portability.
  • Added LSApplicationCategoryType = public.app-category.developer-tools.
  • STRING_CATALOG_GENERATE_SYMBOLS = YES for both build configs.
  • Toolbar refactor: ToolbarItemToolbarItemGroup; HStack { Image; Text }Label("New Task", systemImage: "plus").

4. README

  • Xcode requirement: 15 → 16+ (Swift 6).
  • API reference link: 4.8.25.0.0.
  • "App ID" terminology updated to Database ID (with note that it was previously called App ID).
  • Removed reference to DITTO_WEBSOCKET_URL in setup steps (Auth URL covers it in v5).

Test plan

  • Build succeeds in Xcode 16+ with strict-concurrency = complete.
  • Cold launch shows ProgressView, then TasksListScreen once initDitto() resolves.
  • Initial four seed tasks appear (Buy groceries / Clean the kitchen / Schedule dentist / Pay bills).
  • Toggle a task's "done" → persists across relaunch.
  • Create / edit / delete tasks via EditScreen — all CRUD paths work.
  • Toggle Sync off/on — ditto.sync.isActive reflects state; subscription is cancelled/recreated.
  • Two devices on the same Database ID sync tasks bidirectionally.
  • Background → foreground after token TTL: auth.expirationHandler re-auths without crash.
  • Navigate away from TasksListScreenteardown() runs (observers cancelled, sync stopped).
  • No purple "Publishing changes from background threads" runtime warnings.

@biozal Aaron LaBeau (biozal) self-assigned this Jan 31, 2026
@biozal Aaron LaBeau (biozal) added the enhancement New feature or request label Jan 31, 2026
@biozal Aaron LaBeau (biozal) changed the title Update Quickstart for Swift to v5 - DO NOT MERGE Draft: Update Quickstart for Swift to v5 - DO NOT MERGE Jan 31, 2026
@biozal Aaron LaBeau (biozal) marked this pull request as ready for review May 5, 2026 14:36
Copilot AI review requested due to automatic review settings May 5, 2026 14:36
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the Swift Tasks quickstart to use DittoSwift v5 APIs and project settings, aligning the sample app’s initialization/sync flows and documentation with the upcoming major release.

Changes:

  • Migrates Ditto initialization and sync calls to the v5 API surface (new DittoConfig/Ditto.open, ditto.sync.*).
  • Updates Xcode project/SwiftPM dependency to DittoSwiftPackage 5.0.0 and adjusts UI toolbar layout.
  • Refreshes the Swift quickstart README links and setup instructions for v5 terminology.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
swift/Tasks/TasksListScreen.swift Updates observer/sync usage for v5 and tweaks toolbar UI (Toggle label / bottom bar button).
swift/Tasks/TasksApp.swift Switches startup to async Ditto initialization via DittoManager.initDitto().
swift/Tasks/TaskModel.swift Adds Foundation import (for Data, UUID, etc.).
swift/Tasks/DittoManager.swift Reworks Ditto lifecycle to async open + auth refresh handler; makes ditto optional/published.
swift/Tasks.xcodeproj/xcshareddata/xcschemes/Tasks.xcscheme Updates scheme metadata (upgrade version).
swift/Tasks.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved Pins DittoSwiftPackage to 5.0.0.
swift/Tasks.xcodeproj/project.pbxproj Removes DittoObjC linkage, updates package requirement, and updates build settings.
swift/README.md Updates prerequisites, API reference link, and setup steps for v5 terms.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread swift/Tasks/DittoManager.swift Outdated
Comment thread swift/Tasks/DittoManager.swift
Comment thread swift/Tasks/TasksListScreen.swift Outdated
Comment thread swift/Tasks/TasksListScreen.swift Outdated
Comment thread swift/Tasks.xcodeproj/project.pbxproj
Comment thread swift/Tasks.xcodeproj/project.pbxproj
Comment thread swift/README.md
Aaron LaBeau (biozal) and others added 3 commits May 5, 2026 09:41
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@biozal Aaron LaBeau (biozal) changed the title Draft: Update Quickstart for Swift to v5 - DO NOT MERGE Draft: Update Quickstart for Swift to v5 May 5, 2026
@biozal Aaron LaBeau (biozal) changed the title Draft: Update Quickstart for Swift to v5 Update Swift Quickstart for Ditto v5 + Swift 6 / strict-concurrency readiness May 5, 2026
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall, approved with a few nits

Comment thread swift/Tasks/DittoManager.swift Outdated
@biozal Aaron LaBeau (biozal) merged commit 5d40745 into main May 5, 2026
3 checks passed
@biozal Aaron LaBeau (biozal) deleted the da-138-update-v5-swift branch May 5, 2026 21:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants