Meet SwiftData

RSS for tag

Discuss the WWDC23 Session Meet SwiftData

View Session

Posts under wwdc2023-10187 tag

28 Posts
Sort by:
Post not yet marked as solved
2 Replies
779 Views
I have a WidgetExtension using SwiftData (same ModelContainer setup used in the WatchApp: @main struct Watch_Widget: Widget { let kind: String = "Watch_Widget" var body: some WidgetConfiguration { StaticConfiguration(kind: kind, provider: Provider()) { entry in Watch_WidgetEntryView(entry: entry) .modelContainer(for: [Model1.self, Model2.self]) } .configurationDisplayName("App") .description("descriptions") } } Here's the same model used in the widget view: struct Watch_WidgetEntryView : View { @Query var models: [Model1] var body: some View { let gaugeVal = models.count Gauge(value: gaugeVal, in: 0...60) { Text("min") } currentValueLabel: { Text(String(Int(gaugeVal))) } .gaugeStyle(.accessoryCircular) .widgetLabel { Text("\(models.count) models") } .containerBackground(.fill.tertiary, for: .widget) } } When I build the WidgetExtension, the following error was thrown and the CK data isn't loaded properly: CloudKit setup failed because there is another instance of this persistent store actively syncing with CloudKit in this process.
Posted
by cvhu.
Last updated
.
Post not yet marked as solved
4 Replies
3k Views
Is SwiftData going to be immediately available to use with iOS 16? I ask because I'm working on an app which I'd like to release around the end of this month, and I'm about to implement CoreData for it, but wanted to see when SwiftData would be available. My guess was that SwiftData is for iOS 17 so I should just stick with CoreData for now and switch over later, but just wanted to check to make sure. Thanks!
Posted Last updated
.
Post marked as solved
3 Replies
1.3k Views
Not sure what I'm doing wrong here. I'm taking this opportunity to add persistence to an app that hadn't had it yet. I followed the session advice but I get this crash when running it: SwiftData/BackingData.swift:201: Fatal error: expected attribute to be Codable The crash is on this line: modelContext.insert(RentSplitDataModel()) The object being created and inserted there is simple and the compiler confirms it does conform to Codable: https://github.com/KyLeggiero/Rent-Split-for-iOS/blob/feature/MVP/Shared/Model/RentSplitDataModel.swift
Posted Last updated
.
Post not yet marked as solved
3 Replies
939 Views
Problem The following code doesn't work: let predicate = #Predicate<Car> { car in car.size == size //This doesn't work } Console Error Query encountered an error: SwiftData.SwiftDataError(_error: SwiftData.SwiftDataError._Error.unsupportedPredicate) Root cause Size is an enum, #Predicate works with other type such as String however doesn't work with enum Enum value is saved however is not filtered by #Predicate Environment Xcode: 15.0 (15A240d) - App Store macOS: 14.0 (23A339) - Release Candidate Steps to reproduce Run the app on iOS 17 or macOS Sonoma Press the Add button Notice that the list remains empty Expected behaviour List should show the newly created small car Actual behaviour List remains empty inspite of successfully creating the small car. Feedback FB13194334 Code Size enum Size: String, Codable { case small case medium case large } Car import SwiftData @Model class Car { let id: UUID let name: String let size: Size init( id: UUID, name: String, size: Size ) { self.id = id self.name = name self.size = size } } ContentView struct ContentView: View { var body: some View { NavigationStack { CarList(size: .small) } } CarList import SwiftUI import SwiftData struct CarList: View { let size: Size @Environment(\.modelContext) private var modelContext @Query private var cars: [Car] init(size: Size) { self.size = size let predicate = #Predicate<Car> { car in car.size == size //This doesn't work } _cars = Query(filter: predicate, sort: \.name) } var body: some View { List(cars) { car in VStack(alignment: .leading) { Text(car.name) Text("\(car.size.rawValue)") Text(car.id.uuidString) .font(.footnote) } } .toolbar { Button("Add") { createCar() } } } private func createCar() { let name = "aaa" let car = Car( id: UUID(), name: name, size: size ) modelContext.insert(car) } }
Posted
by newwbee.
Last updated
.
Post not yet marked as solved
6 Replies
1.3k Views
I've been testing out SwiftData but haven't bee able to get ModelContext notifications working. I've tried both an objc observer and for await patterns but it never fires. If I listen for the older nsmanagedcontext notifications they are firing, but I am hoping that the new ones give an ID instead of an objectId. Has anyone got these working? Attempt 1: class NotificationObserver { init() { let didSaveNotification = ModelContext.didSave NotificationCenter.default.addObserver(self, selector: #selector(didSave(_:)), name: didSaveNotification, object: nil) } @objc func didSave(_ notification: Notification) { print(notification.name) } } Attempt 2: class NotificationObserver { init() { let didSaveNotification = ModelContext.didSave Task { for await note in NotificationCenter.default.notifications(named: didSaveNotification) { print(note) } } } }
Posted
by pnewelljr.
Last updated
.
Post not yet marked as solved
0 Replies
553 Views
I have a Model Class Note: @Model class Note { var id: UUID var created: Date var content: String @Relationship(inverse: \Event.notes) var events: [Event]? init(_ content: String, created: Date = .now, events: [Event] = []) { self.id = UUID() self.created = created self.content = content self.events = events } } And Event: @Model class Event: Hashable, Equatable { var id: String var name: String var eventNotes: String? @Relationship var notes: [Note]? // @Transient does not publish (iOS bug?), use .ephemeral instead @Attribute(.ephemeral) var isSelected: Bool = false init(_ name: String = "Unnamed Event", calendarId: String, eventNotes: String) { self.id = calendarId self.name = name self.eventNotes = eventNotes } init(from calendarEvent: EKEvent) { self.id = calendarEvent.eventIdentifier self.name = calendarEvent.title self.eventNotes = calendarEvent.notes ?? "" } ... static func loadEvents(date: Date = Date()) -> [Event] { ... } } I have the following View hierarchy NoteInputView which has @State var events: [Event] = [] SelectEventButton which has @Binding var events: [Event] and calls Event.loadEvent() to retrieve list of events SelectEventSheet which has @Binding var events: [Event] and lets the user toggle isSelected GitHub Gist with all relevant files Adding notes with same events crashes... With this setup, I attempt so save new notes in NoteInputView by calling addNote: func addNote() -> Note { let selectedEvents = events.filter({ $0.isSelected }) let note = Note(newNoteContent, events: selectedEvents) context.insert(note) do { try context.save() } catch { print(error) } return note } This works for the first note after opening the app, or if every subsequent note has a different event selected. However, storing a second note with the same event crashes with the following error: "Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Illegal attempt to establish a relationship 'events' between objects in different contexts" (complete error see here) The error occurs at context.insert, which doesn't throw. If I force quit the app, and then add a note with the same events as an already persisted note, no error is thrown (until a I add another note with the same event without force-quitting). ... but not because one cannot refer to the same events twice It's not a problem of referring to the same events, as the following code also works fine for multiple notes: func addNote() -> Note { // This works, despite notes also always referring to the same events let note = Note(newNoteContent, events: Event.loadEvents()) context.insert(note) do { try context.save() } catch { print(error) } return note } . ... workaround? Manually adding events to the context before adding it to the notes One workaround seems to be to add the events to the context before adding the note: func addNote() -> Note { let selectedEvents = events.filter({ $0.isSelected }) selectedEvents.forEach({context.insert($0)}) let note = Note(newNoteContent, events: events) context.insert(note) do { try context.save() } catch { print(error) } return note } . ... but why? While this works, I cannot quite make sense of this. It seems that passing events around between views may be the culprit, or that loadEvents is called in a child view. Would love some advice, since this doesn't seem like intended behavior.
Posted
by henningko.
Last updated
.
Post not yet marked as solved
4 Replies
2.6k Views
Hey, I am trying to save an enum in my model with SwiftData but getting a weird error message I do not understand at the moment, and I am pretty sure I am missing something here. public enum URLScheme: String, Codable { case https case http } @Model public class MyModel { public var urlScheme: URLScheme } When I try to save the model I get the following error message in the console: error: Row (pk = 1) for entity 'MyModel' is missing mandatory text data for property 'https' I was wondering if I need to tell SwiftData how to save my enum ? My assumption was that I can save any enum if it conforms to Codable. Am I doing something wrong here or is this a beta bug ? Thanks a lot for helping
Posted Last updated
.
Post not yet marked as solved
22 Replies
2.9k Views
When running a macOS app on Xcode 15 Beta 5 (15A5209g), I get a Symbol Not Found error. Problem: App will not run. Error received. Symbol Not Found: SwiftData Default Backing For AC Environment: Version 15.0 beta 5 (15A5209g), macOS 14.0 Beta (23A5257q) App: macOS SwiftData Model @Model class Audit { init() { } } Error: dyld[875]: Symbol not found: _$s9SwiftData014DefaultBackingB0C3forACyxGxm_tcfC Referenced from: <75DF3350-4DD5-3AF4-80DA-B17B0EDD26C2> /Users/dking/Library/Developer/Xcode/DerivedData/{redacted}-bigzojxvffztaaaepdczriowvoie/Build/Products/Debug/{redacted}.app/Contents/MacOS/{redacted} Expected in: /System/Library/Frameworks/SwiftData.framework/Versions/A/SwiftData
Posted
by dkk277.
Last updated
.
Post not yet marked as solved
4 Replies
1.3k Views
I have an App Group shared between my app and its widgets. I have SwiftData's @Model, updated from the widget intent's perform() method and displayed on the app and the widget. @MainActor func perform() async throws -> some IntentResult { let context = try ModelContainer(for: MyModel.self).mainContext let myModel = try ModelContainer(for: MyModel.self).mainContext.fetch( FetchDescriptor<MyModel>(predicate: #Predicate { // The predicate is not the problem. }) ).first myModel?.functionThatModifiesMyModel() return .result() } Both the app and the widget SwiftUI views access to the model using Macros. @Environment(\.modelContext) var context @Query(sort: \.whatever) var myModel: [MyModel] But the data is never correct in the app code (the widget's data is updated correctly using the intent). Why doesn't the model make it to the app?
Posted
by serg-ios.
Last updated
.
Post not yet marked as solved
0 Replies
456 Views
PersistentModel is a protocol but would make more sense as a class that we then subclass. If all of the implementation was in a parent class of our model classes then there wouldn't be all the problems caused by requiring the use of the @Model macro, e.g. default property values not working, unable to subclass, overriding get/set not possible, conflict in property names...
Posted
by malc.
Last updated
.
Post not yet marked as solved
1 Replies
813 Views
The Sendable documentation says we can mark reference types as Sendable if they "internally manage access to their state." Adding Sendable conformance to my SwiftData classes silences warnings such as the following: "Non-sendable type '[Item]' returned by implicitly asynchronous call to nonisolated function cannot cross actor boundary" @Model final class Item: Sendable { var sampleProperty = "" } My understanding is that the compiler would complain if adding explicit Sendable conformance to a swift data model was breaking concurrency rules, but I wanted to check with the community to see what everyone thinks. Best, Taylor
Posted
by taychap.
Last updated
.
Post not yet marked as solved
2 Replies
947 Views
I'm trying to instantiate my model and I'm getting an error on the set first property import Foundation import SwiftData @Model final class PointModel { var x: CGFloat var y: CGFloat init( x: CGFloat, y: CGFloat ) { self.x = x self.y = y } } extension PointModel { static var preview: PointModel { PointModel(x: 0, y: 0) } } let point = PointModel(x: location.x, y: location.y) { get { _$observationRegistrar.access(self, keyPath: \.x) return self.getValue(for: \.x) } set { _$observationRegistrar.withMutation(of: self, keyPath: \.x) { self.setValue(for: \.x, to: newValue) **Thread 1: Fatal error: Illegal attempt to use a nil as an Attribute - x + 151.0** } } } Has anyone else experienced this problem? Maybe someone knows how to solve this?
Posted
by Nizelan.
Last updated
.
Post marked as solved
4 Replies
3.3k Views
re: the SwiftData session "Create an app with SwifData" (https://developer.apple.com/videos/play/wwdc2023/10154) I corrected the @MainActor issue, but it seems to only work with the main ContentView and not other views. I get the following error for TripListItem for example : failed to find a currently active container for Trip
Posted
by grangej.
Last updated
.
Post not yet marked as solved
2 Replies
642 Views
Hi all, I am trying to render my SwiftUI views that uses SwiftData classes using sample data using the approach shown in the example code of wwdc2023-10196: @MainActor #Preview { TripsWidgetEntryView() .modelContainer(PreviewSampleData.container) } Unfortunately this seems no longer valid. Indeed I get this error: I then tried to remove the @MainActor as suggested, but the error in then moved to another level: What do you suggest to be the best approach to have back my preview working? I am using Xcode Beta 4 - 15A5195m
Posted Last updated
.
Post not yet marked as solved
3 Replies
1.1k Views
Hello, I have just tried playing around with the new Swift Data framework and noticed something. Assume the following many-to-many relationship on two PersistentModels: @Model class Media { @Relationship(.nullify, inverse: \Tag.medias) var tags: [Tag] } @Model class Tag { var medias: [Media] } This compiles without problems. If we now make Media conform to Codable (or just Decodable), we get a compiler error: "Ambiguous use of 'getValue(for:)'". When expanding the @Model and the then revealed @PersistedProperty macro, we see that the error is in the getter of Tag.medias, where we call self.getValue(for: \.medias). It seems the compiler knows multiple overloads of this function, including: an overload that accepts a KeyPath with a PersistentModel value an overload that accepts a KeyPath with a Decodable value Since Media conforms to both protocols, the compiler understandably does not know which overload to use. So to my questions: Is this intended behavior? So are PersistentModels not supposed to be Decodable? If yes, what would be the preferred way (or a clean way) to decode a PersistentModel (e.g., from an API)? Best regards, Jonas
Posted Last updated
.
Post not yet marked as solved
1 Replies
1.5k Views
Just for grins, I tried running the SwiftData generation tool on the existing Core Data model of a non-trivial app I've worked on for a decade or so. It's pretty substantial, and uses some more advanced features, so it seemed like an interesting test case. One of the warnings that was not reported by the UI, but which showed up in the generated code was quite a few instances of this: Entity inheritance on entity Bar (parent class Foo) is unsupported in SwiftData. Now that I'm looking at the code examples more carefully, I see an awful lot of final class, which maybe should have raised a red flag sooner. But to the best of my recollection, none of the sessions outright said that inheritance (was or) was not supported. Core Data has supported this functionality for a long time (maybe since the beginning). Assuming that this isn't supported in this first seed, are there plans to provide this functionality in the future? By the launch of iOS 17? (For the record, this model has 93 entities, of which 34 have parent entities. 14 are abstract, which I gather is also not supported. 3 of the entities are both abstract and have parent entities.)
Posted
by 610.
Last updated
.
Post not yet marked as solved
3 Replies
1.2k Views
Using SwiftData, I have a model that uses an enum as a property and a custom Codable type import SwiftData import CoreLocation // MARK: - Main Model @Model class Cache { var size: CacheSize? var coordinates: CLLocationCoordinate2D } // MARK: - CacheSize Enum enum CacheSize: CaseIterable, Codable { case nano case micro case small case regular case large case veryLarge case notChosen case virtual case other } // MARK: - Codable for CLLocationCoordinate2D extension CLLocationCoordinate2D: Codable { enum CodingKeys: String, CodingKey { case lat, lng } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(self.latitude, forKey: .lat) try container.encode(self.longitude, forKey: .lng) } public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let latitude = try container.decode(CLLocationDegrees.self, forKey: .lat) let longitude = try container.decode(CLLocationDegrees.self, forKey: .lng) self.init(latitude: latitude, longitude: longitude) } } When I fetch the object from the ModelContext and try to access the property corresponding to this enum, I have a fatal error raised in BackingData.swift: SwiftData/BackingData.swift:197: Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.typeMismatch(iGeo.CacheSize, Swift.DecodingError.Context(codingPath: [], debugDescription: "Invalid number of keys found, expected one.", underlyingError: nil)) When I try to read the CLLocationCoordinates2D property, I have also a crash in the Decodable init(from decoder: Decoder implementation when trying to read the first value from the container. Did I miss something here or did something wrong?
Posted
by yageekCH.
Last updated
.
Post marked as solved
2 Replies
1.6k Views
When trying to delete the element from my list, I always got error in my model. get { _$observationRegistrar.access(self, keyPath: \.id) return self.getValue(for: \.id) <-- ERROR: Thread 1: EXC_BREAKPOINT (code=1, subcode=0x1a949aefc) } Because I am new in development, I don't know how to solve it.
Posted Last updated
.