Post not yet marked as solved
I am trying to store usdz files with SwiftData for now.
I am converting usdz to data, then storing it with SwiftData
My model
import Foundation
import SwiftData
import SwiftUI
@Model
class Item {
var name: String
@Attribute(.externalStorage)
var usdz: Data? = nil
var id: String
init(name: String, usdz: Data? = nil) {
self.id = UUID().uuidString
self.name = name
self.usdz = usdz
}
}
My function to convert usdz to data. I am currently a local usdz just to test if it is going to work.
func usdzData() -> Data? {
do {
guard let usdzURL = Bundle.main.url(forResource: "tv_retro", withExtension: "usdz") else {
fatalError("Unable to find USDZ file in the bundle.")
}
let usdzData = try Data(contentsOf: usdzURL)
return usdzData
} catch {
print("Error loading USDZ file: \(error)")
}
return nil
}
Loading the items
@Query private var items: [Item]
...
var body: some View {
...
ForEach(items) { item in
HStack {
Model3D(?????) { model in
model
.resizable()
.scaledToFit()
} placeholder: {
ProgressView()
}
}
}
...
}
How can I load the Model3D?
I have tried:
Model3D(data: item.usdz)
Gives me the errors:
Cannot convert value of type '[Item]' to expected argument type 'Binding<C>'
Generic parameter 'C' could not be inferred
Both errors are giving in the ForEach.
I am able to print the content inside item:
ForEach(items) { item in
HStack {
Text("\(item.name)")
Text("\(item.usdz)")
}
}
This above works fine for me.
The item.usdz prints something like Optional(10954341 bytes)
I would like to know 2 things:
Is this the correct way to save usdz files into SwiftData? Or should I use FileManager? If so, how should I do that?
Also how can I get the usdz from the storage (SwiftData) to my code and use it into Model3D?
Post not yet marked as solved
iPad mini device with iPadOS 17.4.1.
I get this failure on iPad mini device exclusively. I have universal app and I doesn't get this error neither on iPhone or any simulator or macOS. I tried to reset the iPad, still getting the error.
The error happens when I send the app to background from the particular app screen.
Here is the error:
error: Store failed to load.
<NSPersistentStoreDescription: 0x3004b4bd0> (type: SQLite, url: file:///dev/null) with error = Error Domain=NSCocoaErrorDomain Code=134060
"A Core Data error occurred."
UserInfo={NSLocalizedFailureReason=The configuration named 'default' does not contain any entities.} with userInfo {
NSLocalizedFailureReason = "The configuration named 'default' does not contain any entities.";
}
What error says is that it loaded the store from file:///dev/null, which is wrong. Basically it looses the model container which is added via modelContaner modificator to the root view.
The error get caused particularly by the @Environment(\.modelContext) private var modelContext call in the view on which the failure occurs. This view is deep in the view hierarchy, and it get's created in the navigationDestination block.
I fixed the error by supplying modelContainer one more time right on the view:
.navigationDestination(for: File.self) { file in
FileEditor(file: file)
.modelContainer(FolderService.modelContainer)
}
I wonder, why can it loose the model container which is supplied on the root view?
Post not yet marked as solved
Recently, I have been using SwiftData as a data persistence tool in my new SwiftUI app.
My app utilizes CLLocationManager for background location tracking to wake up the app and update SwiftData-related data. When the app is in the foreground or background, SwiftData's @Query can normally retrieve data. However, once the user manually terminates the app and it receives a location-based wake-up, SwiftData's @Query no longer retrieves data. I have looked through many resources and haven't found any similar documentation. I wonder if anyone can give me some suggestions?
Post not yet marked as solved
I have v3 models in coredata (model: Event, Lecture), and make new model in v4 with swiftdata but model name, property is different (model: EventModel, LectureModel).
For migration, I add V3Schema, V4Schema and MigrationPlan.
enum V4Schema: VersionedSchema {
static var models: [any PersistentModel.Type] = [LectureModel.self, EventModel.self ]
static var versionIdentifier = Schema.Version(4, 0, 0)
}
enum V3Schema: VersionedSchema {
static var models: [any PersistentModel.Type] = [Event.self, Lecture.self]
static var versionIdentifier = Schema.Version(3, 5, 2)
}
enum ModelMigrationPlan: SchemaMigrationPlan {
static var schemas: [any VersionedSchema.Type] = [V3Schema.self, V4Schema.self]
static var stages: [MigrationStage] = [migrateV3ToV4]
}
extension ModelMigrationPlan {
static let migrateV3ToV4 = MigrationStage.custom(fromVersion: V3Schema.self,
toVersion: V4Schema.self,
willMigrate: willMigrate,
didMigrate: { _ in Log.debug(message: "Migration Complete") })
}
private func willMigrate(context: ModelContext) throws {
try migrateLectures(context: context)
try migrateEvents(context: context)
try context.save()
}
private func migrateEventTypes(context: ModelContext) throws {
// create new v4 event model using v3 event model.
}
private func migrateLectures(context: ModelContext) throws {
// create new v4 lecture model using v3 lecture model.
}
static let release: ModelContainer = {
let v4Schema = Schema(V4Schema.models)
let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "app group id")
let databaseURL = containerURL?.appending(path: "**.sqlite")
let configuration = ModelConfiguration("**",
schema: v4Schema,
url: databaseURL!,
cloudKitDatabase: .private("**"))
#if DEBUG
do {
try autoreleasepool {
let desc = NSPersistentStoreDescription(url: configuration.url)
let opts = NSPersistentCloudKitContainerOptions(containerIdentifier: configuration.cloudKitContainerIdentifier!)
desc.cloudKitContainerOptions = opts
desc.shouldAddStoreAsynchronously = false
if let model = NSManagedObjectModel.makeManagedObjectModel(for: V4Schema.models) {
let container = NSPersistentCloudKitContainer(name: "**", managedObjectModel: model)
container.persistentStoreDescriptions = [desc]
container.loadPersistentStores(completionHandler: { _, err in
if let err {
Log.error(message: "Store open failed: \(err.localizedDescription)")
}
})
try container.initializeCloudKitSchema()
Log.debug(message: "Initialize Cloudkit Schema")
if let store = container.persistentStoreCoordinator.persistentStores.first {
try container.persistentStoreCoordinator.remove(store)
}
}
}
} catch {
Log.error(message: "Failed: \(error.localizedDescription)")
}
#endif
return try! ModelContainer(for: v4Schema, migrationPlan: ModelMigrationPlan.self, configurations: configuration)
}()
But when I run, I got error message.
CoreData: CloudKit: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _scheduleAutomatedExportWithLabel:activity:completionHandler:]_block_invoke(3508): <NSCloudKitMirroringDelegate: 0x1036b1540> - Finished automatic export - ExportActivity - with result: <NSCloudKitMirroringResult: 0x1035da810> storeIdentifier: ***** success: 0 madeChanges: 0 error: Error Domain=NSCocoaErrorDomain Code=134407 "Request '*****' was cancelled because the store was removed from the coordinator." UserInfo={NSLocalizedFailureReason=Request '****' was cancelled because the store was removed from the coordinator.}
I don't know why store was removed from the coordinator.
Any have solutions?
Post not yet marked as solved
I have a situation where tapping on a NavigationLink on an item from a SwiftData Query results in an infinite loop, causing the app the freeze. If you run the code, make sure to add at least 1 item, then tap on it to see the issue.
Here is the code for a small sample app I made to illustrate the issue:
import SwiftUI
import SwiftData
@main
struct TestApp: App {
var sharedModelContainer: ModelContainer = {
let schema = Schema([
Item.self
])
let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)
do {
let container = try ModelContainer(for: schema, configurations: [modelConfiguration])
return container
} catch {
fatalError("Could not create ModelContainer: \(error)")
}
}()
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(sharedModelContainer)
}
}
struct ContentView: View {
var body: some View {
NavigationStack {
ListsView()
}
}
}
struct ListsView: View {
@Environment(\.modelContext) private var modelContext
@Query(filter: #Predicate<Item> { _ in true })
private var items: [Item]
var body: some View {
List(items) { item in
NavigationLink {
ItemDetail()
} label: {
VStack {
Text("\(item.name) | \(item.date.formatted())")
}
}
}
Button("Add") {
let newItem = Item(name: "Some item", date: .now)
modelContext.insert(newItem)
try? modelContext.save()
}
}
}
struct ItemDetail: View {
private var model = ItemModel()
var body: some View {
VStack {
Text("detail")
}
}
}
fileprivate var count = 0
class ItemModel {
var value: Int
init() {
value = 99
print("\(count)")
count += 1
}
}
@Model
final class Item {
let name: String
let date: Date
init(name: String, date: Date) {
self.name = name
self.date = date
}
}
In the test app above, the code in the initializer of ItemModel will run indefinitely. There are a few things that will fix this issue:
comment out the private var model = ItemModel() line in ItemDetail view
replace the @Query with a set list of Items
move the contents of the ListsView into the ContentView instead of referencing ListsView() inside the NavigationStack
But I'm not sure why this infinite loop is happening with the initializer of ItemModel. It seems like a SwiftData and/or SwiftUI bug, because I don't see a reason why this would happen. Any ideas? Has anyone run into something similar?
Post not yet marked as solved
I know if i change existing properties in a @Model it’s a migration. However if I add a new @Model class(es) that has no relationships to any existing is that still a migration or am i free to add?
if free to add, should i create a new model container or can I just add the new Model classes ?
Post not yet marked as solved
I am new to Swift, and I am trying to get a grip on SwiftData, which SO FAR seems pretty straightforward EXCEPT relationships between tables. I come from a MYSQL, SQLITE3 background and I am used to “Primary Keys”, Inner and Outer Joins, One-to-One and One-to-Many relationships. Which SwiftData does not appear to do (I think).
I am following several reasonably good online tutorials on the subject, all of which gloss over how relationships work. The best one is a table for vegetables alongside a table of notes for each vegetable (A one-to-many relationship). The classes we set up for the schemas are as follows.
import Foundation
import SwiftData
@Model
class Vegetable {
var name: String
@Relationship(deleteRule: .cascade) var notes: [Note]?
init(name: String) {
self.name = name
}
}
@Model
class Note {
var text: String
var vegetable: Vegetable?
init(text: String) {
self.text = text
}
}
I can’t comprehend how they work. None of the tutorials I have watched explain it or explain it in a way I can understand.
In the “Vegetable” class, why is the field “notes” an array of type Notes?
Again in the “Vegetable” class does the field “notes” get stored in the database, if so what is stored?
In the “Note” Class it looks like the whole of the class “Vegetable” gets stored in the variable “vegetable”, which may or may not get stored in the database.
I've run into a problem related to navigation links in child Views containing a SwiftData @Query and a predicate.
When tapping on a NavigationLinks, the containing View is invalidated pausing the UI. When tapping back, the View is invalidated a second time during which time the View ignores any new taps for navigation leading to a poor user experience.
A complete example:
import SwiftUI
import SwiftData
@Model
final class Item {
var num: Int
init(num: Int) {
self.num = num
}
}
@main
struct TestSwiftDataApp: App {
var sharedModelContainer: ModelContainer = {
let schema = Schema([Item.self])
let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: true)
let container: ModelContainer
do {
container = try ModelContainer(for: schema, configurations: [modelConfiguration])
} catch {
fatalError("Could not create ModelContainer: \(error)")
}
// Add some sample data
Task { @MainActor in
for i in 0...1000 {
container.mainContext.insert(Item(num: i))
}
}
return container
}()
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(sharedModelContainer)
}
}
extension Color {
static func random() -> Color {
Color(red: .random(in: 0...1), green: .random(in: 0...1), blue: .random(in: 0...1))
}
}
struct ContentView: View {
var body: some View {
NavigationStack {
SubView()
.navigationDestination(for: Item.self) { item in
Text("Item at \(item.num)")
}
}
}
}
struct SubView: View {
@Environment(\.modelContext) private var modelContext
@Query(filter: #Predicate<Item> { item in
item.num < 20
}, sort: \.num) private var items: [Item]
var body: some View {
let _ = Self._printChanges()
List {
ForEach(items) { item in
NavigationLink(value: item) {
Text("Item \(item.num)")
}.background(Color.random())
}
}
}
}
The background colors of cells will shift every invalidation. In addition there's some debugging in there to show what's happening. When running it, I get
SubView: @self, @identity, _modelContext, @128, @144 changed.
SubView: @self changed.
SubView: @dependencies changed.
Then I tap on an item and it invalidates:
SubView: @self changed.
Tapping back invalidates it again during which time the UI ignores new taps:
SubView: @self changed.
The odd thing is, this behavior doesn't happen if the NavigationStack is moved to the child View with the NavigationLinks like this:
struct ContentView2: View {
var body: some View {
SubView2()
}
}
struct SubView2: View {
@Environment(\.modelContext) private var modelContext
@Query(filter: #Predicate<Item> { item in
item.num < 20
}, sort: \.num) private var items: [Item]
var body: some View {
let _ = Self._printChanges()
NavigationStack {
List {
ForEach(items) { item in
NavigationLink(value: item) {
Text("Item \(item.num)")
}.background(Color.random())
}
}
.navigationDestination(for: Item.self) { item in
Text("Item at \(item.num)")
}
}
}
}
When running this, there's one less change as well and no invalidations on tap or back:
SubView: @self, @identity, _modelContext, @128, @144 changed.
SubView: @dependencies changed.
The problem also doesn't happen if the @Query does not have a filter #Predicate.
Unfortunately, the application in question has a deeper hierarchy where views with a @Query with a predicate can navigation to other views with a @Query and predicate, so neither solution seems ideal.
Is there some other way to stop the invalidations from happening?
Post not yet marked as solved
SwiftData includes support for CloudKit sync. However, I don't see any way to add conflict resolution behavior. For example, if different devices set different values for a field, or if a relationship is orphaned because of a deletion on another device, the application has to handle this somehow.
In Core Data (which SwiftData wraps), you can handle this with the conflict resolution system (docs) and classes like NSMergePolicy.
Is any of this accessible in SwiftData? If not, how do you deal with conflicts when syncing a SwiftData model with the cloud?
Post not yet marked as solved
Hi,
I'm about to adopt .externalStorage but I will also use CloudKit in the near future. I did not find any reference that list of requirements for SwiftData models to be used with CloudKit, only for Core Data models.
It seems those Core Data requirements (like no-unique) apply to SwiftData as well. However I did not find any info on this:
Can @Attribute(.externalStorage) be used when I want to sync my model with CloudKit?
Post not yet marked as solved
Hi! Not sure if this is a swift data or more a Decimal in general type of question.
What's going on:
I have a SwiftUI app using SwiftData, I have persisted a Model with a property "reducedPrice" of type Decimal. It's stores correctly the value.
Now, I have read the value during automated tests and tried comparing the values:
let reducedPrice = model.reducedPrice // swift data property
let target = Decimal(4.98) // expected target value to compare to swift data value.
Now if I just print the result of the comparison between those 2 I get a false result.
print(reducedPrice == target) //output : false
The swift data model was populated from a direct copy of another struct that comes from an JSON import using Codable+CodingKeys (I used Decimal type).
What I expected:
I expected it to be true.
Debug Observations
I did noticed that on the variable inspector both had the same magnitudes but in reality the mantissa are different. I'm attaching a screenshot.
My Theory
They are different just because something under SwiftData stores different way the decimal as in comparison on how I am creating the Decimal for the comparison inside the automated tests.
My question
Is this expected behavior?
Any suggestion on best practices on how to handle this?
Thank you in advance any relevant guidance is very appreciated!
Post not yet marked as solved
I'm developing an app with a chart in SwiftUI. I want the following block of code to run when the chart is clicked. On my personal iPhone, the app works flawlessly. But when I try it in the simulator it crashes and gives me about 5-10 of the following errors. When I remove the @Query macro from the code block, the application does not crash in the simulator, but I continue to get the errors I mentioned. If I do not run the following code block, I do not get the errors I mentioned.
struct SaleDetailView: View {
@Query(filter: #Predicate<Registration> {
!$0.activeRegistration
}) private var regs: [Registration]
var body: some View {
VStack {
DailySaleView()
}
.padding()
}
}
Thank you in advance for your answers. Do not hesitate to ask if you have any questions.
Thanks, MFS
Post not yet marked as solved
Dear all,
I have the following two classes:
Stagioni:
import SwiftData
@Model
class Stagione {
@Attribute(.unique) var idStagione: String
var categoriaStagione: String
var miaSquadra: String
@Relationship(deleteRule: .cascade) var rosa: [Rosa]?
@Relationship(deleteRule: .cascade) var squadra: [Squadre]?
@Relationship(deleteRule: .cascade) var partita: [CalendarioPartite]?
init(idStagione: String, categoriaStagione: String, miaSquadra: String) {
self.idStagione = idStagione
self.categoriaStagione = categoriaStagione
self.miaSquadra = miaSquadra
}
}
CalendarioPartite:
import SwiftData
@Model
class CalendarioPartite {
var idGiornata: Int
var dataPartita: Date
var squadraCasa: String
var squadraTrasferta: String
var golCasa: Int
var golTrasferta: Int
var stagione: Stagione?
init(idGiornata: Int, dataPartita: Date, squadraCasa: String, squadraTrasferta: String, golCasa: Int, golTrasferta: Int) {
self.idGiornata = idGiornata
self.dataPartita = dataPartita
self.squadraCasa = squadraCasa
self.squadraTrasferta = squadraTrasferta
self.golCasa = golCasa
self.golTrasferta = golTrasferta
}
}
Now, I'd like to have a query which is showing in a view the list of partite depending on a selection of a specific Stagione.
I've tried with the following query, but I'm getting the following error: "Instance member 'selectedStagione' cannot be used on type 'CalendarioCampionatoView'; did you mean to use a value of this type instead?"
@Query(filter: #Predicate<CalendarioPartite> { $0.stagione == selectedStagione}) private var partite: [CalendarioPartite] = []
What I'm doing wrong?
Thanks,
A.
Post not yet marked as solved
Can anyone give me assistance on how to fix this. My preview crashed because a Fatal Error in ModelData.
This is how my ModelData looks:
import SwiftUI
struct SutraokeDetail: View {
@Environment(ModelData.self) var modelData
var sutra: Sutras
var body: some View {
@Bindable var modelData = modelData
ScrollView {
CircleImage(image: sutra.image)
.offset(y: -130)
.padding(.bottom, -130)
VStack(alignment: .leading) {
HStack{
Text(sutra.name)
.font(.title)
Spacer()
Text(sutra.text)
}
}
}
}
}
#Preview {
let modelData = ModelData()
return SutraokeDetail(sutra: modelData.sutras[0])
.environment(modelData)
}
Post not yet marked as solved
UPDATED: I determined the line causing the hang was .animation(.default, value: layout).
I'm seeing a strange issue when switching between a ScrollView/LazyVGrid and a List with my SwiftData but when toggling the layout it ends up freezing and I can't confirm what's causing the app to hang since there's no crash. I'm not getting much info from the debugger. Any help would be appreciated.
struct ContentView: View {
@Environment(\.modelContext) private var modelContext
@Query private var items: [Item]
let gridItemLayout = [ GridItem(.adaptive(minimum: 150))]
@State private var layout = Layout.grid
var body: some View {
NavigationStack {
ZStack {
if layout == .grid {
ScrollView {
LazyVGrid(columns: gridItemLayout, spacing: 5) {
ForEach(items) { item in
}
}
}
} else {
List {
ForEach(items) { item in
}
}
}
}
// MARK: HERE'S THE ERROR
.animation(.default, value: layout)
.navigationTitle("ScrollView")
.toolbar {
ToolbarItemGroup {
Button(action: addItem) {
Label("Add Item", systemImage: "plus")
}
Menu {
Picker("Layout", selection: $layout) {
ForEach(Layout.allCases) { option in
Label(option.title, systemImage: option.imageName)
.tag(option)
}
}
.pickerStyle(.inline)
} label: {
Label("Layout Options", systemImage: layout.imageName)
.labelStyle(.iconOnly)
}
}
}
}
}
}
@Model
public class Item: Codable {
public let id: String
public enum CodingKeys: String, CodingKey {
case id
}
public init(id: String) {
self.id = id
}
required public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(String.self, forKey: .id)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
}
}
Post not yet marked as solved
Has anyone successfully persisted Color, particularly in SwiftData? So far my attempts have failed:
Making Color conform to Codable results in a run time error (from memory something about ColorBox).
Color.Resolved already conforms Codable but this results in "SwiftData/ModelCoders.swift:124: Fatal error: Composite Coder only supports Keyed Container"
None of the other color types conform to Codable (CGColor, NSColor and UIColor) so does the swift language really not have a persistable color type?
Post not yet marked as solved
Hello everyone, I looked at various methods how to Unit/UITest SwiftData but I couldn't find something simple. Is it even possible to test SwiftData? Does someone found a solution for that?
I have been working on an ios application which I decided to use the new SwiftData architecture, and I now have realized that SwiftData does not support public or shared databases using SwiftData.
I am a new and upcoming Swift developer, who has been self learning the Apple Swift technology. I just learned in this forum that Swift Data does not support Public and Shared Data and I also understand that no plans that have been announced to addressed this feature in the IOS 18 release time frame.
The use case for my application is to implement a social type application, something like applications including X, facebook, etc. These type of applications appear to use Public, Shared and Private data in various existing Apple application.
I would like to complete an application using Swift using ICloud, but I must assume that these current social applications are using other technologies. I am assuming you can do this in Core Data, but my understanding is Apple is asking that we use Swift Data to replace core data. I also am assuming that Swift data is built on core data technology layers. So ... to me it seems hopeful, somehow, to accomplish this using IOS 17 and follow the recommend Swift Data Path.
What are my options for completing these data objectives in IOS? I hope I am addressing these questions in the proper and best forum? Much thanks for any suggestions.
Post not yet marked as solved
I have an Apple app that uses SwiftData and icloud to sync the App's data across users' devices. Everything is working well. However, I am facing the following issue:
SwiftData does not support public sharing of the object graph with other users via iCloud. How can I overcome this limitation without stopping using SwiftData?
Thanks in advance!
Post not yet marked as solved
It's been frustrating to solve this error. My iOS device and Xcode are fully updated. I can easily run app on simulator, but issue happens on my iPhone.
dyld[23479]: Symbol not found: _$s9SwiftData12ModelContextC6insert6objectyx_tAA010PersistentC0RzlFTj
Referenced from: <6FC773BB-E68B-35A9-B334-3FFC8B951A4E> Expected in: /System/Library/Frameworks/SwiftData.framework/SwiftData