iCloud & Data

RSS for tag

Learn how to integrate your app with iCloud and data frameworks for effective data storage

CloudKit Documentation

Post

Replies

Boosts

Views

Activity

SwiftData appending values to Query
Hi, I am trying to create somethings like an infinite scroll view with SwiftData but I am not able to figure out how to append elements to the @Query result. Let's say I have 1000 entries in my DB but I only want to load 40 at a time. If the user scrolls to the last element of the result I want to load the next batch of 40 entries. That is the code: import SwiftData import OSLog private let logger = Logger(subsystem: "SetsTab", category: "SetsTab") struct SetsTab: View { @Environment(\.modelContext) private var modelContext @Binding var searchText: String @Query private var sets: [SetModel] @State private var fetchLimit = 40 @State private var offset = 0 init(searchText: Binding<String>) { _searchText = searchText if searchText.wrappedValue.isEmpty { var fetchDesc = FetchDescriptor<SetModel>() fetchDesc.fetchLimit = fetchLimit fetchDesc.fetchOffset = offset _sets = Query(fetchDesc) } else { let term = searchText.wrappedValue let setCodePred = #Predicate<SetModel> { $0.name.contains(term) } var fetchDesc = FetchDescriptor<SetModel>(predicate: setCodePred) fetchDesc.fetchLimit = fetchLimit fetchDesc.fetchOffset = offset _sets = Query(fetchDesc) } } var body: some View { ScrollView{ LazyVStack{ ForEach(sets){actSet in VStack{ Text("Set: \(actSet.name)") } .onAppear { self.loadMoreContentIfNeeded(currentItem: actSet) } } }} .onAppear { for i in 1...1000 { let set = SetModel(name: "Set \(i)") modelContext.insert(set) } try! modelContext.save() } } func loadMoreContentIfNeeded(currentItem item: SetModel?) { if sets.endIndex < self.fetchLimit { return } guard let item = item else { loadMoreContent() return } let thresholdIndex = sets.index(sets.endIndex, offsetBy: -5) if sets.firstIndex(where: { $0.id == item.id }) == thresholdIndex { loadMoreContent() } } private func loadMoreContent() { self.offset += self.fetchLimit loadMoreSets() } private func loadMoreSets(){ logger.info("Loading more Sets with offset \(self.offset)") let term = searchText let setCodePred = #Predicate<SetModel> { $0.name.contains(term) } do{ var fetchDesc = FetchDescriptor<SetModel>(predicate: setCodePred) fetchDesc.fetchLimit = self.fetchLimit fetchDesc.fetchOffset = self.offset var newBatchOfSets = try modelContext.fetch(fetchDesc) logger.info("new Batch of Sets count: \(newBatchOfSets.count)") // sets.append(contentsOf: newBatchOfSets) } catch{ logger.error("\(error.localizedDescription)") } } } The logic for registering when to load the new batch works so loadMoreSets() is called correctly but to actually fetch the new batch and appending to the already fetched data is missing. I commented this part: sets.append(contentsOf: newBatchOfSets) because it is giving me the error: Cannot use mutating member on immutable value: 'sets' is a get-only property so basically telling me that the @Query var sets can only be set inside the initializer. So how can we realise something like an infinite scroll view with SwiftData? I feel that this is an valid and for me mandatory use case when working with thousands of db entries in order to be performant. Has anybody realised this in a different way? Best regards, Sven
0
0
645
Aug ’23
Is migration working for anyone on Xcode beta6?
Hi, I am trying my first SwiftData migration, but my custom migration stage never gets called. Since I am not sure if this is a bug with the current beta of if I am "holding it wrong" I was wondering, if anybody got migration working (their MigrationStage.custom called)? Would be great, if you could just let me know, if you got it working or running into the same issue! :-) Thank you! Cheers, Michael
1
0
844
Aug ’23
SwiftData Array in random order?
Why is the order of my array random when i use the @Model macro. class TestModel { var name: String? var array: [TestModel2] init(name: String = "") { self.name = name array = [] } } class TestModel2 { var name: String? init(name: String = "") { self.name = name } } This works fine, and all the items in array are in the order I add them. But if I declare both of them as @Model, like this: @Model class TestModel { var name: String? var array: [TestModel2] init(name: String = "") { self.name = name array = [] } } @Model class TestModel2 { var name: String? init(name: String = "") { self.name = name } } The array items are always in a random order. When I reload the view where they are displayed or when I add items to the array the order is randomised. Is this a beta bug? Or is this intended?
6
6
1.3k
Aug ’23
What does transaction(block:) actually do?
I'm working on an app where I want to add a large amount of data to SwiftData, but roll back if any errors occur during this process. SwiftData has a method called transaction (linked below), but it does not have any documentation and I can't find any info about it online. What does it actually do? https://developer.apple.com/documentation/swiftdata/modelcontext/transaction(block:)
0
1
316
Aug ’23
SwiftData self-referencing model has wierd behavior
I have a model like this: @Model final class TreeNodeModel{ var createdAt: Date var title: String var content: String //Relations @Relationship(deleteRule:.cascade) var children: [TreeNodeModel]? init(title:String,content:String = "",) { self.title = title self.content = content } } When I try to insert models like below (works well): let parent = TreeNodeModel(title: "parent") let child = TreeNodeModel(title: "child") parent.children!.append(child) modelContext.insert(parent) But if try to insert models like below (wierd things happened): not only parent has one children [child], child also has one children [parent] let parent = TreeNodeModel(title: "parent") modelContext.insert(parent) let child = TreeNodeModel(title: "child") parent.children!.append(child) This is quit wierd, anyone has met this kind of issue?
2
1
674
Aug ’23
All of my iCloud Data is Gone
I was testing out iOS 17 Beta 5 with Advanced Data Protection turned on. I wanted to downgrade to iOS 16 for improved stability; however, once I downgraded all of my iCloud data was gone (~100GB) and about 10+ years of digital accumulation poof. Yes, I'm on the correct iCloud account. Yes, I'm logged in. Yes, I've checked iCloud.com as well as my device. Yes, I went back to iOS 17 Beta 5 to see if my backup would show up but there is no data and no backup anywhere else. I was discussing with apple tech support for over an hour and they were unable to assist. Just checking if anyone else might have suggestions on other things to try.
0
0
426
Aug ’23
Swift compiler crashes with simple SwiftData model
In Xcode 15 beta 6, the swift compiler crashes with a simple SwiftData model. The model compiles OK, but any attempt to instantiate the entity in code, including a unit test, will crash the compiler. A stack track is provided with a note to submit a bug report. Some SwiftData classes work without error, but this example will crash. Cannot find any workaround and am forced to remain on beta 5 for now. Anyone else experiencing this? Works without error in beta 5. Compiler crashes in a basic unit test on this line, or any other attempt to instantiate the model. let note = Note(content: "Went for a bike ride this morning!") public final class Note: Identifiable { @Attribute(.unique) public private(set) var id: UUID? public private(set) var createdDate: Date public private(set) var updatedDate: Date /// Optional title for this note public var title: String? { didSet { updatedDate = Date() } } /// Note content public var content: String? { didSet { updatedDate = Date() } } public init(title: String? = nil, content: String) { self.id = UUID() self.createdDate = Date() self.updatedDate = Date() self.title = title self.content = content } }
14
0
1.9k
Aug ’23
SwiftData: Accessing collection from computed property forces dependency update ?!? and this compute property and so on... cycle
If I comment let _ = entries everything goes well, but if not, accessing(not editing) the collection I don't know why forces the view update (dependency change in items) and with the view update the computed property checkingDate is triggered firing the view update... and so on. Cycle Why accessing entries forces view update ? If I change let _ = entries for let _ = name everything goes well so I conclude that is a problem with collection... Models: @Model final class Item { var name: String @Relationship(deleteRule:.cascade) var entries: [Entry] init(name: String) { self.name = name entries = [] } } extension Item { @Transient var checkingDate: Date { let _ = entries // < -- !!! //... return Date() } } @Model final class Entry { var value: Int var date: Date init(value: Int, date: Date) { self.value = value self.date = date } } View: struct ContentView: View { @Query(sort: \Item.name) private var items: [Item] @Environment(\.modelContext) private var context var body: some View { let _ = Self._printChanges() List{ ForEach(items){item in Text("Name:\(item.name), checking date: \(item.checkingDate, format: Date.FormatStyle(date: .numeric, time: .standard))") } } } }
4
0
536
Aug ’23
SwiftData. Predicate. Issue accessing self (Entity) inside a Predicate
@Model final class Entry { var value: Int var date: Date var item: Item? init(value: Int, date: Date) { self.value = value self.date = date } } @Model final class Item { var name: String @Relationship(deleteRule:.cascade, inverse: \Entry.item) var entries: [Entry] init(name: String) { self.name = name entries = [] } } extension Item { func checkingDate(in context: ModelContext)->Date{ try! context.fetch(FetchDescriptor<Entry>(predicate:#Predicate<Entry>{$0.item == self})).last!.date } } same if self == self Why I'm fetching and not directly accessing entries: https://developer.apple.com/forums/thread/735735
3
0
913
Aug ’23
Is it safe to mark SwiftData (@Model) classes as Sendable?
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
2
1
1.2k
Aug ’23
SwiftData Crash - After Developer Beta Update to iOS 17.0 (21A5312c)
Running on Version 15.0 beta 6 (15A5219j) Crash on launch (replicatable with a new template iOS project with SwiftData in addition to my existing project). Error on launch looks like this: dyld[8046]: Symbol not found: _$s9SwiftData15PersistentModelP14schemaMetadataSaySS_s10AnyKeyPathCypSgAGtGyFZTq Referenced from: <CFCE9A78-4C88-3DCA-AA36-643C911902C4> /private/var/containers/Bundle/Application/8F5A5864-78B5-42DD-9481-9AABC79AFCF4/TestThisNew.app/TestThisNew Expected in: <8B52C2B3-931A-3736-B357-ECF87A41F3EB> /System/Library/Frameworks/SwiftData.framework/SwiftData Message from debugger: killed
5
7
955
Aug ’23
"This NSPersistentStoreCoordinator has no persistent stores", despite setting up all capabilities
Hi guys, First of all, I'm sorry if this is the wrong place to post this. I'm in the last steps of my task manager app: getting the tasks to sync between devices. However, I get the error "This NSPersistentStoreCoordinator has no persistent stores (unknown). It cannot perform a save operation." What does this error exactly mean? My container is initialised so it should have a persistent store, right? I've also enabled all the proper capabilities I'm pretty sure (eg, I've enabled CloudKit, created a container, enabled background fetch and remote notifications.) Here is the code for my data controller: import CoreData import Foundation class DataController: ObservableObject { let container = NSPersistentCloudKitContainer(name: "TaskDataModel") init() { guard let description = container.persistentStoreDescriptions.first else { fatalError("Container descriptions not loaded") } description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey) container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy container.viewContext.automaticallyMergesChangesFromParent = true container.loadPersistentStores { description, error in if let error = error { print("Core Data failed to load: \(error.localizedDescription)") } } } } Here is TaskManMain: @main struct TaskManApp: App { @StateObject private var dataController = DataController() var body: some Scene { WindowGroup { MainView() .environment(\.managedObjectContext, dataController.container.viewContext) } } } Here is the full repo if y'all are interested: https://github.com/aabagdi/TaskMan Thanks for any help!
1
0
890
Aug ’23
Usage of CKQueryOperation.recordMatchedBlock and .queryResultBlock
Anyone know the correct usage for CKQueryOperation.recordMatchedBlock and .queryResultBlock? Xcode is telling me to use them as the old .recordFetchedBlock and .queryCompletionBlock are deprecated, but there isn't any documentation to say how they should be used. ChatGPT, Bard etc aren't able to provide a correct answer either: specifically, I need to convert the following to use those methods: operation.recordFetchedBlock = { record in // Convert CKRecord to Core Data object and save to Core Data self.saveToCoreData(record: record) } operation.queryCompletionBlock = { (cursor, error) in // Handle potential errors if let error = error { print("Error syncing first of month records: \(error)") } if let cursor = cursor { // There are more records to fetch for this category, continue fetching self.continueSyncing(cursor: cursor, completion: completion) } else { // Done syncing this category, move to the next sync task completion() } }
1
0
522
Aug ’23
Failed to find a currently activated model container
Hi, i'm trying out SwiftData in Xcode 15.0 beta 5. I’m building a POC of a Note app using SwiftData for the data persistence. I started by creating a new model SimpleNote, where i could successfully implement a CRUD of a note. Now i want to add a new feature introducing the TODO list, however when i tried add the new relationship between the new model TodoItem to SimpleNote the app crashes with the following error: NotesPOC crashed due to fatalError in ModelContainer.swift at line 167. failed to find a currently active container for SimpleNote Both models works fine independently, only crashes when the Relationship is set. I tried to clean simulator data, remove DerivedData, clean the Build Folder but nothing works. The code: SimpleNote.swift: final class SimpleNote: Identifiable { let uuid = UUID() var title: String = "" var content: String = "" var createdAt: Date = Date() var modifiedAt: Date = Date() var theme: String = "" @Relationship(.cascade) var todoList: [TodoItem] = [] init(title: String, content: String, createdAt: Date, modifiedAt: Date, todoList: [TodoItem]) { self.title = title self.content = content self.createdAt = createdAt self.modifiedAt = modifiedAt self.theme = Theme.random().rawValue self.todoList = todoList } } TodoItem.swift: import Foundation import SwiftData @Model class TodoItem: Identifiable { let uuid = UUID() var isCompleted: Bool = false var content: String = "" init(isCompleted: Bool, content: String) { self.isCompleted = isCompleted self.content = content } } NoteApp.swift: import SwiftData @main struct StickyNotesPOCApp: App { var body: some Scene { WindowGroup { NavigationStack { ContentView() .frame(maxWidth: .infinity, maxHeight: .infinity) .background(.black) } } .modelContainer(for: [SimpleNote.self, TodoItem.self]) } } Has anyone faced this issue? am i missing something?
1
2
1.2k
Aug ’23
Swiftdata - unsupportedPredicate for enum properties - XCode 15 b7
Hello, I'm trying to use a #Predicate filtering by an Enum property. But in runtime I getSwiftData.SwiftDataError._Error.unsupportedPredicate Somehow I couldn't find any recent posts related to this issue. Has anyone encountered this or been able to solve/workaround it? Will it be ever fixed? What is the point in supporting stored enums if I cannot use them to run a query? I'm struggling with this since beta 1, it really seems that SwiftData is not a priority for Apple right now. I'm really trying to stick with it but I'm running into issues that are indefinitely delaying all my development every day. @Model final class ModelA { var name: String enum ModelAType: Int, Codable { case type1 = 1, type2 } var type: ModelAType // ... } // ... let predicateConstant = ModelA.ModelAType.type1 #Predicate<ModelA> { $0.type == predicateConstant }
3
5
1.3k
Aug ’23
Can't add values to Relationship?
Hi There, i'm not sure if anything changed in Beta 7 or it's me being an ***** but I can't seem to update my relationship property, anyone else experienced this? @Model final class Goal { // More properties here @Relationship(deleteRule: .cascade, inverse: \Progress.goal) var progress: [Progress]? init(progress: [Progress]? = []) { self.progress = progress } func updateProgress(with value: Double) { // I've also tried this with having the modelContext in the initialiser let context = ModelContext(DataStore.container) let newProgress = Progress(date: Date.now, value: value) newProgress.goal = self context.insert(newProgress) self.progress?.append(newProgress) // Other code } } @Model final class Progress { var progressDate: Date? var value: Double? var goal: Goal? init(date: Date = Date.now, value: Double = 0.0, goal: Goal? = nil) { self.progressDate = date self.value = value self.goal = goal } } Everytime I call the updateProgress method I get a fatal error (e.g. goal.updateProgress(with: 33.2) The Error Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for to-one relationship: property = "goal"; desired type = NSManagedObject; given type = NSManagedObject; value = <NSManagedObject: 0x2823e0c80> (entity: Goal; id: 0x8617307020b13c03 <x-coredata://7AE46844-B3C6-46A3-B350-FC65B7CCDF8F/Goal/p17>; data: { // Properties here }) I've tried many different ways but without any luck… In case this is a bug: FB13034172
3
7
948
Aug ’23
SwiftData does not work on a background Task even inside a custom ModelActor.
I have created an actor for the ModelContainer, in order to perform a data load when starting the app in the background. For this I have conformed to the ModelActor protocol and created the necessary elements, even preparing for test data. Then I create a function of type async throws to perform the database loading processes and everything works fine, in that the data is loaded and when loaded it is displayed reactively. actor Container: ModelActor { nonisolated let modelContainer: ModelContainer nonisolated let modelExecutor: ModelExecutor static let modelContainer: ModelContainer = { do { return try ModelContainer(for: Empleados.self) } catch { fatalError() } }() let context: ModelContext init(container: ModelContainer = Container.modelContainer) { self.modelContainer = container let context = ModelContext(modelContainer) self.modelExecutor = DefaultSerialModelExecutor(modelContext: context) self.context = context Task { do { try await loadData() } catch { print("Error en la carga \(error)") } } } } The problem is that, in spite of doing the load inside a Task and that there is no problem, when starting the app it stops responding the UI while loading to the user interactions. Which gives me to understand that actually the task that should be in a background thread is running somehow over the MainActor. As I have my own API that will provide the information to my app and refresh it at each startup or even send them in Batch when the internet connection is lost and comes back, I don't want the user to be continuously noticing that the app stops because it is performing a heavy process that is not really running in the background. Tested and compiled on Xcode 15 beta 7. I made a Feedback for this: FB13038621. Thanks Julio César
7
1
3.9k
Aug ’23
SwiftData Autosave and Last Updated Timestamp
I have in my model a date created attribute and a date last updated attribute. When adding a new item, I set both to the current timestamp. However, on an update I would like to be able to have the autosave option auto-update the last updated date automatically. Turning off autosave and doing it manually is challenging to get right. Does anyone know of a solution to this such as extending ModelContext? It seems like last updated date would be a common model requirement.
1
0
914
Aug ’23