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

Xcode 15.2b Transformable Properties Crash App
This possibly seems like a regression but from iOS 17.1.0+, I'm having issues from Xcode 15.2 Beta &where when using a transformable property I'm getting a crash when trying to create a model container. This worked fine for me in Xcode 15.1 Beta when testing on iOS OS 17.0.1 and below. I have a simple model where I'm trying to save a UIColor, below is an example of this model. class Category: Codable { @Attribute(.unique) var title: String var items: [Item]? @Attribute(.transformable(by: ColorValueTransformer.self)) var color: UIColor? init(title: String = "", color: UIColor) { self.title = title self.color = color } enum CodingKeys: String, CodingKey { case title } required init(from decoder: Decoder) throws { ... } func encode(to encoder: Encoder) throws { ... } } Within my value transformer, I'm handling setting and getting the value. final class ColorValueTransformer: ValueTransformer { static let name = NSValueTransformerName(rawValue: String(describing: ColorValueTransformer.self)) override func transformedValue(_ value: Any?) -> Any? { guard let color = value as? UIColor else { return nil } do { let data = try NSKeyedArchiver.archivedData(withRootObject: color, requiringSecureCoding: true) return data } catch { return nil } } override func reverseTransformedValue(_ value: Any?) -> Any? { guard let data = value as? Data else { return nil } do { let color = try NSKeyedUnarchiver.unarchivedObject(ofClass: UIColor.self, from: data) return color } catch { return nil } } public static func register() { let transformer = ColorValueTransformer() ValueTransformer.setValueTransformer(transformer, forName: name) } } Then within my root app entry point, I register this transformer. @main struct ToDosApp: App { ...... init() { ColorValueTransformer.register() } ...... Unfortunately in my custom container object I get a crash on this line let container = try ModelContainer(for: ....) With an error of Thread 1: EXC_BAD_ACCESS (code=1, address=0x0) Like i said before previously this was working fine but now it's not... I have a feedback open also FB13471979 but it would be great if someone on the SwiftData team at Apple could look into this issue since it's a pretty big regression...
5
0
1.1k
Dec ’23
How to add multiple ModelConfigurations to a ModelContainer?
Anyone successfully able to add two or more ModelConfigurations to a ModelContainer? DESCRIPTION OF PROBLEM: When you create two ModelConfigurations for two different models and combine them into one ModelContainer, it seems the @Query fails to find the models. Crashes app with error: “Thread 1: "NSFetchRequest could not locate an NSEntityDescription for entity name 'NumberModel'" STEPS TO REPRODUCE 1 - Create a new iOS project. 2 - In ContentView.swift add this code: import SwiftData import SwiftUI struct ContentView: View { @Query private var colors: [ColorModel] @Query private var numbers: [NumberModel] var body: some View { List { ForEach(colors) { color in Text(color.name) } ForEach(numbers) { number in Text(number.name) } } } } #Preview { ContentView() .modelContainer(for: [ColorModel.self, NumberModel.self]) } 3 - In App file, add this code: import SwiftData import SwiftUI @Model class ColorModel { var name: String = "" init(name: String) { self.name = name } } @Model class NumberModel { var name: String = "" init(name: String) { self.name = name } } @main struct MultipleModelConfigsApp: App { private var container: ModelContainer init() { do { let config1 = ModelConfiguration(for: ColorModel.self) let config2 = ModelConfiguration(for: NumberModel.self) let container = try ModelContainer( for: ColorModel.self, NumberModel.self, configurations: config1, config2 ) self.container = container } catch { fatalError("ModelContainer creation failed.") } } var body: some Scene { WindowGroup { ContentView() .modelContainer(container) } } } 4 - Now run the app and observe the crash and the error stated above. VERSION OF XCODE Version 15.1 (15C65) FEEDBACK REPORT FB: FB13504577 (Xcode project attached to FB)
4
2
1.1k
Dec ’23
SwiftData/ModelContainer.swift:144: Fatal error: failed to find a currently active container for Student
I am currently following the tutorial from Hacking with swift url: (https://www.hackingwithswift.com/books/ios-swiftui/introduction-to-swiftdata-and-swiftui) to integrate SwiftData into a SwiftUI project. The code generated based on the tutorial is provided below. However, an error occurs upon launching the app: SwiftData/ModelContainer.swift:144: Fatal error: failed to find a currently active container for Student. I am seeking assistance in resolving this issue. import SwiftUI import SwiftData @Model class Student { var id: UUID var name: String init(id: UUID, name: String) { self.id = id self.name = name } } @main struct project8App: App { var body: some Scene { WindowGroup { VStack { ContentView() } } .modelContainer(for: Student.self) } } struct ContentView: View { @Environment(\.modelContext) var modelContext @Query var students: [Student] let allStudents = [ Student(id: UUID(), name: "John"), Student(id: UUID(), name: "Paul"), Student(id: UUID(), name: "George"), Student(id: UUID(), name: "Ringo"), ] var body: some View { VStack { ForEach(students) { student in Text("\(student.name)") } Button(action: { // random student let student = allStudents.randomElement()! modelContext.insert(student) }) { Text("Add/Change name") } } } } P.S. It appears that the problem may be related to the container not being initialized by .modelContainer(for: Student.self). I have managed to resolve the error with the modified version below. However, I am still curious about the reasons behind the original version's malfunction and the differences between the two implementations. // version 2, which is ok to run @main struct project8App: App { let modelContainer: ModelContainer init() { do { modelContainer = try ModelContainer(for: Student.self) } catch { fatalError("Could not initialize ModelContainer") } } var body: some Scene { WindowGroup { VStack { ContentView() } } .modelContainer(modelContainer) } }
1
0
1.5k
Jan ’24
CloudKit Data Startup Issue
Afternoon all, I am starting out and want to store data in the App, some will be user specific and some general. So I have a new developer account which should have CloudKit permissions. I am just trying to make any of the most basic example applications work, but keep hitting issues. I create an App, select CloudKit and SwiftData. When I go into the signing and capabilities I select the Team which has the developer account. Then the CloudKit is selected as I clicked it when creating the project, but no Container is selected. I create a Container using the +, it names it iCloud.com.mydomain.AppName. However it is coloured in Red text. I press the refresh and then it turns into black text, the Push Notifications appear all populated for 1 second then all disappear. I have nothing under Push now, only a Trashcan button. The Container is now selected however. Is this an issue that the Push notifications items appeared then vanished? When I then try to run the app, using any of the many attempts I have had with simple code samples, it always fails to create the Container, usually with an error like this: error: Store failed to load. <NSPersistentStoreDescription: 0x600000c79ce0> (type: SQLite, url: file:///Users/cal/Library/Developer/CoreSimulator/Devices/6D2BA1B3-C7CA-499D-A280-AFF4C5E98180/data/Containers/Data/Application/B9CD5E35-08BD-44CC-A72D-EB170E3691C6/Library/Application%20Support/default.store) with error = Error Domain=NSCocoaErrorDomain Code=134060 "A Core Data error occurred." UserInfo={NSLocalizedFailureReason=CloudKit integration requires that all attributes be optional, or have a default value set. The following attributes are marked non-optional but do not have a default value: Item: name} with userInfo { NSLocalizedFailureReason = "CloudKit integration requires that all attributes be optional, or have a default value set. The following attributes are marked non-optional but do not have a default value:\nItem: name"; If I go into the CloudKit database view on Apple, I see the Container listed, albeit it is marked as not deployed to production. To try to remove my newbie issues I have used many web examples, the most recent of which was the "A Beginner’s Guide to SwiftData with a to-do app" from medium.com, which should just work really, snipped from Item.swift below but I have tried several other simple examples which all give the same issue: import Foundation import SwiftData @Model class Item: Identifiable { var name: String init(name: String){ self.name = name } } Any ideas really appreciated. Thank you
2
0
791
Jan ’24
CloudKit Web Services with ASP.NET Core server to server key auth
Hello, I have an iOS app that is still in development, and I am also making a website for it with asp.net core. I am trying to use a server to server key, but it isn't working. The response is: { "uuid" : "some_uuid", "serverErrorCode" : "AUTHENTICATION_FAILED", "reason" : "Authentication failed" } I am using a library called EllipticCurve. You can find it here. My code is: var requestData = new { zoneID = new {}, query = new { recordType = "CD_Person", filterBy = new [] { new { comparator = "EQUALS", fieldName = "CD_email", fieldValue = new { value = email, type = "String" } } }, sortBy = new [] { new { fieldName = "CD_email" } } }, zoneWide = "true", numbersAsStrings = "true" }; string request = JsonSerializer.Serialize(requestData); HttpClient client = new HttpClient(); client.DefaultRequestHeaders.Add("X-Apple-CloudKit-Request-KeyID", "my_key_id"); DateTime date = DateTime.Now; string iso8601Date = date.ToUniversalTime().ToString("u").Replace(" ", "T"); client.DefaultRequestHeaders.Add("X-Apple-CloudKit-Request-ISO8601Date", iso8601Date); byte[] bytes = Encoding.UTF8.GetBytes(request); SHA256 hashstring = SHA256.Create(); byte[] hash = hashstring.ComputeHash(bytes); string base64Request = Convert.ToBase64String(hash); string paramsToSign = $"{iso8601Date}:{base64Request}:my url"; PrivateKey privateKey = PrivateKey.fromPem("-----BEGIN EC PRIVATE KEY-----\nprivate_key\n-----END EC PRIVATE KEY-----"); Signature signature = Ecdsa.sign(paramsToSign, privateKey); client.DefaultRequestHeaders.Add("X-Apple-CloudKit-Request-SignatureV1", signature.toBase64()); var content = new StringContent(request, Encoding.UTF8, "application/json"); var response = client.PostAsync("https://api.apple-cloudkit.com/database/1/my_container/development/public/records/query", content); string responseString = response.Result.Content.ReadAsStringAsync().Result; Console.WriteLine(responseString); return View(); Any help would be appreciated.
0
0
477
Jan ’24
Saving images to core data runs of memory
I'm trying to do a mass conversion of images to data so it can be stored in core data. The conversion part works fine, and if I do it without updating core data it shows memory usage at less that 100MB If I update the core data object, it just keeps consuming memory until the app crashes. func updateLocalImages() { let fetchRequest: NSFetchRequest<Picture> = Picture.fetchRequest() fetchRequest.predicate = NSPredicate(format: "pictureName != \"\"") do { let pictures = try moc.fetch(fetchRequest) print("Picture Update Count: \(pictures.count)") for picture in pictures { let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) let path = paths[0] if let picName = picture.pictureName { let imagePath = path.appendingPathComponent(picName) if let uiImage = UIImage(contentsOfFile: imagePath.path) { if let imageData = uiImage.jpegData(compressionQuality: 1.0) { autoreleasepool { picture.pictureData = imageData print("Picture Updated") saveContext() } } } } } } catch { print("Fetching Failed") } } If I comment out the picture.pictureData = imageData line I don't get the memory issues. What's the correct way of going about this? There is an unknown number of images (mine current sits at about 5.5GB worth, 800+)
1
0
495
Jan ’24
Can CloudKit security rules be scoped to an application?
I'm building two apps. They both share a CloudKit container. One application is designed to edit the contents of the public database regardless of who a record's creator is. The other should only be allowed to read from the public database. Since CloudKit is largely a client-side framework it's easy enough to enforce this client side. Are there any additional guarantees that iCloud provides to enforce what the clients are signed to do? Or is there a risk of having some actor tamper with the public database that isn't using the editing application?
0
0
531
Jan ’24
SwiftData+CloudKit,AppGroups Error
I use SwiftData, CloudKit, and App Groups. An error occurs on the first run, but it works on the second run. error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate tearDown:]_block_invoke(792): <NSCloudKitMirroringDelegate: 0x12df73750>: Told to tear down with reason: Store Removed error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _performSetupRequest:]_block_invoke(1192): <NSCloudKitMirroringDelegate: 0x12df73750>: Failed to set up CloudKit integration for store: (null) Error Domain=NSCocoaErrorDomain Code=134060 "" UserInfo={NSLocalizedFailureReason=The mirroring delegate could not initialize because it's store was removed from the coordinator.} I don't know why store path is null in error message. I passed the store url and CloudKit database name in ModelConfiguration. static var release: ModelContainer = { do { let schema = Schema(versionedSchema: ModelSchema.self) let appGroupURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group-identifier") let databaseURL = appGroupURL?.appending(path: "Database.sqlite") let databaseName = "Database" let configuration = ModelConfiguration(schema: schema, url: databaseURL!, cloudKitDatabase: .private("iCloud.database.name")) return try ModelContainer(for: schema, migrationPlan: ModelMigrationPlan.self, configurations: [configuration]) } catch { fatalError(error.localizedDescription) } }()
2
1
584
Jan ’24
Core Data modifications not saved in two of three tables
I'm a bit lost because of a problem I never experienced before, however, I have a suspicion. I use Core Data for data storage and DB Browser for SQLite for inspecting the database running in the Simulator. Here's the relevant function where all Core Data handling happens: /** Creates a new ComposedFoodItem from the ComposedFoodItemViewModel. Creates the related FoodItem and the Ingredients. Creates all relationships. - Parameter composedFoodItemVM: The source view model. - Returns: A Core Data ComposedFoodItem; nil if there are no Ingredients. */ static func create(from composedFoodItemVM: ComposedFoodItemViewModel, generateTypicalAmounts: Bool) -> ComposedFoodItem? { debugPrint(AppDelegate.persistentContainer.persistentStoreDescriptions) // The location of the .sqlite file let moc = AppDelegate.viewContext // Create new ComposedFoodItem (1) let cdComposedFoodItem = ComposedFoodItem(context: moc) // No existing composed food item, therefore create a new UUID cdComposedFoodItem.id = UUID() // Fill data cdComposedFoodItem.amount = Int64(composedFoodItemVM.amount) cdComposedFoodItem.numberOfPortions = Int16(composedFoodItemVM.numberOfPortions) // Create the related FoodItem (2) let cdFoodItem = FoodItem.create(from: composedFoodItemVM, generateTypicalAmounts: generateTypicalAmounts) // Relate both (3) cdComposedFoodItem.foodItem = cdFoodItem // Add cdComposedFoodItem to composedFoodItemVM composedFoodItemVM.cdComposedFoodItem = cdComposedFoodItem // Save before adding Ingredients, otherwise this could lead to an NSInvalidArgumentException (4) try? moc.save() // Add new ingredients (5) if let cdIngredients = Ingredient.create(from: composedFoodItemVM) { cdComposedFoodItem.addToIngredients(NSSet(array: cdIngredients)) // Save new composed food item try? moc.save() // Return the ComposedFoodItem return cdComposedFoodItem } else { // There are no ingredients, therefore we delete it again and return nil moc.delete(cdComposedFoodItem) try? moc.save() return nil } } What the function does: Creates a new entry in table ComposedFoodItem Creates another new entry in another table FoodItem Relates both entries Saves the modifications (and as of here I can see both new entries in the DB with all relations created correctly) Creates another 1..n entries in a third table Ingredient and links these to the entry created in step 1 All this works fine, I can see all relations and entries in the database. Then I quit and restart the app. The entry created in step 2 is still there, but the entries created in steps 1 and 5 are gone, as well as the relationships (of course). My suspicion: I recently implemented a Core Data migration from Data Model version 1 ("EasyFPU") to version 2 ("EasyFPU 2"). In this migration, I have two custom migration policies for exactly the two tables, which are not stored. The migration policies are pretty simple (and identical for both tables): /** No Ingredient is created in the destination model, i.e., there will be no Ingredients */ override func createDestinationInstances(forSource sourceIngredient: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws { // Do nothing on purpose debugPrint("Not migrating Ingredient with ID: \((sourceIngredient as? Ingredient)?.id.uuidString ?? "unknown")") } And what I suspect is, that this migration policies are somehow called when restarting the app, but I have no idea why, because the migration has already happened before. If I set a breakpoint in the debugPrint line of the code snippet above, I actually never reach this breakpoint - as expected. Nevertheless are the two tables Ingredient and ComposedFoodItem empty after restart. My AppDelegate Core Data persistentContainer variable looks like this: lazy var persistentContainer: NSPersistentCloudKitContainer = { let container = NSPersistentCloudKitContainer(name: "EasyFPU") container.loadPersistentStores(completionHandler: { (storeDescription, error) in if let error = error as NSError? { fatalError("Unresolved error \(error), \(error.userInfo)") } }) return container }() I tried to replace "EasyFPU" with "EasyFPU 2", but this apparently is not the version, but the container name. Any idea? Thanks in advance!
0
0
319
Jan ’24
TooManyProviderTokensUpdates - how many is too many
Our service is 100% on token-based authentication with APNs. Each pod generates a new token to use every 30 mins. We have hundreds of pods. We implemented this way because in Refresh your token regularly section it says Refresh your token no more than once every 20 minutes and no less than once every 60 minutes. APNs report an error if you use a new token more than once every 20 minutes on the same connection. However, we saw TooManyProviderTokensUpdates sporadically. What is even stranger is, the trigger of the error does not correlate to the number of pods as we scaled up or down, nor does it correlate to the QPS. To me, it looks like It triggers randomly. Can someone from Apple shed some light on this?
0
1
308
Jan ’24
SwiftData multiple Models - Thread 1: "NSFetchRequest could not locate an NSEntityDescription for entity name 'PastTripData'"
It works fine if I take either model out, but it doesn't work with both I have tried multiple variations import SwiftData import Foundation @main struct blendTravelfourApp: App { @Environment(\.modelContext) var context var body: some Scene { WindowGroup { ContentView() .modelContainer(for: PlanTripData.self) .modelContainer(for: PastTripData.self) } } } import SwiftData @main struct blendTravelfourApp: App { var container: ModelContainer init() { do { let config1 = ModelConfiguration(for: PlanTripData.self) let config2 = ModelConfiguration(for: PastTripData.self) container = try ModelContainer(for: PlanTripData.self, PastTripData.self, configurations: config1, config2) } catch { fatalError("Failed to configure SwiftData container.") } } var body: some Scene { WindowGroup { ContentView() .modelContainer(container) } } }
2
4
1.2k
Jan ’24
SwiftData filter many to many relationship
my question is how to filter in search text for city.name in Concert ? i tried to reach city name using nested compact map but couldn't handle it. class Concert { var kindOf : String var city : [City] } class City { var name : String @Relationship(inverse: \Concert.city) var concert : [Concert] } @Query var concerts : [Concert] @State var searchQuery : String = "" var filteredConcert : [Concert] { if searchQuery.isEmpty { return concerts } let filteredConcerts = concerts.compactMap { concert in let kindOfContainsSearch = concert.kindOf.range(of: searchQuery) != nil return (kindOfContainsSearch ) ? concert : nil } return filteredConcerts }
0
0
343
Jan ’24
Can SwiftData Registered Models Be Equal Values and Different References?
Hi! I'm experimenting with SwiftData and looking for a situation where one persistentModelID might result in more than one registered model object reference delivered from a fetch from a single context. Here is an example of what I have to experiment: import Foundation import SwiftData @Model class Person { var name: String init(name: String) { self.name = name } } func main() { let configuration = ModelConfiguration( isStoredInMemoryOnly: true, allowsSave: true ) do { let container = try ModelContainer( for: Person.self, configurations: configuration ) let context = ModelContext(container) let person = Person(name: "John Appleseed") context.insert(person) let persistentModelID = person.persistentModelID if let left: Person = context.registeredModel(for: persistentModelID), let right: Person = context.registeredModel(for: persistentModelID) { print(left === right) // true } let descriptor = FetchDescriptor<Person>( predicate: #Predicate { person in person.persistentModelID == persistentModelID } ) if let left = try context.fetch(descriptor).last, let right = try context.fetch(descriptor).last { print(left === right) // true } } catch { print(error) } } main() This is a very simple command line app that attempts to fetch "two different" registered models… but both approaches (querying directly for persistentModelID and wrapping persistentModelID with FetchDescriptor) seem to consistently deliver objects equal by reference. Is there any situation where I could set this code up to deliver two registered models different by reference (but equal by value)? Is this anything I have to think about or manage at an "app" level? Is this behavior documented anywhere? Thanks!
0
0
634
Jan ’24
SwiftData with CloudKit failing to migrate schema
My app has been in the App Store a few months. In that time I've added a few updates to my SwiftData schema using a MigrationPlan, and things were seemingly going ok. But then I decided to add CloudKit syncing. I needed to modify my models to be compatible. So, I added another migration stage for it, changed the properties as needed (making things optional or adding default values, etc.). In my tests, everything seemed to work smoothly updating from the previous version to the new version with CloudKit. So I released it to my users. But, that's when I started to see the crashes and error reports come in. I think I've narrowed it down to when users update from older versions of the app. I was finally able to reproduce this on my end, and Core Data is throwing an error when loading the ModelContainer saying "CloudKit integration requires that all attributes be optional, or have a default value set." Even though I did this in the latest schema. It’s like it’s trying to load CloudKit before performing the schema migration, and since it can’t, it just fails and won’t load anything. I’m kinda at a loss how to recover from this for these users other than tell them to delete their app and restart, but obviously they’ll lose their data that way. The only other idea I have is to setup some older builds on TestFlight and direct them to update to those first, then update to the newest production version and hope that solves it. Any other ideas? And what can I do to prevent this for future users who maybe reinstall the app from an older version too? There's nothing special about my code for loading the ModelContainer. Just a basic: let container = try ModelContainer( for: Foo.self, Bar.self, migrationPlan: SchemaMigration.self, configurations: ModelConfiguration(cloudKitDatabase: .automatic) )
5
3
2.1k
Jan ’24
Delay in CKRecord uploads
Hi, I have recently noticed that it's taking my app a long time between the CKModifyOperations being 'completed' in the app, and for the record to actual show up through either looking at the CloudKit dashboard, or by using CKQueryOperations. The whole upload can take 10-15 minutes or more, from the time the CKOperation has completed to the time I can see all the records on the dashboard. The 'upload' seems to be happening in chunks ... for e.g. if I uploaded a 100 records, if I check after 2 minutes the query will show 20 records, and then 35-40 a bit later, and after 10+ minutes will show all 100 records (exact numbers vary of course). This was never an issue before, but has recently been reported by a couple of users of my app, and I need to know what's going on before it balloons into a big thing. And it's highly problematic, because it leads to users not being able to download the records that they uploaded on the first device. Is there something in CloudKit servers that have changed recently? Can someone in the CloudKit team take a look? I filed a Feedback, along with CloudKit profile logs: FB13537245 I can also reproduce the issue in production as well as development environments.
1
0
446
Jan ’24
Use SwiftData Crash When #Preview
the Model Code import Foundation import SwiftData @Model class TestItemTotal { var id = UUID() var name: String var describe: String init(name: String = "", describe: String = "") { self.name = name self.describe = describe } } the contentView code import SwiftUI class ShareData: ObservableObject { @Published var path: NavigationPath = NavigationPath() @Published var selectedTestItemTotal = TestItemTotal() } struct ContentView: View { @StateObject var shareData = ShareData() var body: some View { NavigationStack(path: $shareData.path) { List{ Text("The Main Project List") Text("The Detail List") } } } } #Preview { ContentView() } Crash it will crash ,when #preview use Xcode , but it will not crash when run in Simulator . fix Crash Remove @Model string , it will not crash , when #preview use Xcode , but i can't remove @Model String , because i will to processing data by SwiftData
2
0
507
Jan ’24
iCloud Drive
/var/mobile/Containers/Data/Application/9DBD5CCD-36A9-4496-93FB-B8EBD679E934/Documents/godai_2024-01-16_09-34-11-445/photo_2024-01-16_09-34-11-452.json..in this debug console folder name "godai_2024-01-16_09-34-11-445" is shown but in iCloud Drive folder name change into example ..how can to fix this issue ??
0
0
388
Jan ’24