I'm working on an app that uses the AppIntents framework to write to a SwiftData persistence. I add the Sendable shared model container to app dependency manager that my intents and entities and queries can use as a dependency.

When I run the app in Swift 5 language mode, the app works without a problem. However, when I change to Swift 6 language mode, the app crashes at runtime at the point where the dependency should be resolved. In both language modes, strict concurrency checking is set to complete.

I've reduced the app to this MVP:

import AppIntents
import SwiftData
import SwiftUI

@main
struct AppDependencyBugApp: App {

	private let modelContainer: ModelContainer

	init() {
		let modelContainer = ModelContainer.shared
		self.modelContainer = modelContainer
		AppDependencyManager.shared.add(dependency: modelContainer)
	}

	var body: some Scene {
		WindowGroup {
			ItemsList()
				.modelContainer(modelContainer)
		}
	}

}

struct ItemsList: View {

	@Query private var items: [Item]

	var body: some View {
		NavigationStack {
			List {
				Section {
					Button("New Item", systemImage: "plus.circle", intent: NewItemIntent())
				}
				ForEach(items) { item in
					VStack(alignment: .leading) {
						Text(item.dateCreated, format: .iso8601)
						Text(item.id.uuidString)
							.monospaced()
							.font(.caption)
					}
				}
			}
			.navigationTitle("Items")
		}
	}

}

struct NewItemIntent: AppIntent {

	static var title: LocalizedStringResource {
		"New Item Intent"
	}

	@Dependency private var modelContainer: ModelContainer

	func perform() async throws -> some IntentResult {
		let act = DivvydeModelActor(modelContainer: modelContainer)
		try await act.newItem()
		return .result()
	}

}

extension ModelContainer {

	@MainActor
	static let shared: ModelContainer = {
		let container: ModelContainer
		do {
			let schema: Schema = .init([Item.self])
			let configuration: ModelConfiguration = .init(schema: schema)
			container = try ModelContainer(for: schema, configurations: configuration)
		} catch {
			preconditionFailure("Model container failed to initialize with error: \(error.localizedDescription)")
		}
		container.mainContext.autosaveEnabled = false
		return container
	} ()

}

@ModelActor
final actor DivvydeModelActor {

	@MainActor
	func newItem() async throws {
		let modelContext = modelContainer.mainContext
		let item = Item()
		modelContext.insert(item)
		try withAnimation {
			try modelContext.save()
		}
	}

}

@Model
final class Item: Identifiable {

	private(set) var id: UUID
	private(set) var dateCreated: Date

	convenience init(date: Date = .now) {
		self.init(id: .init(), dateCreated: date)
	}

	private init(id: ID, dateCreated: Date) {
		self.id = id
		self.dateCreated = dateCreated
	}

}

Am I missing something out of the Swift concurrency picture or if this is a bug in the framework?

1 Like