Post

Replies

Boosts

Views

Activity

Reply to MAJOR Core Data Issues with iOS 18 and sdk - Data Missing for many users?!
Well something changed since we switched to iOS 18 SDK and it definitely did not work this way in earlier versions of iOS. At some point after iOS 15 SDK something changed and the "cleaning" process you mentioned is literally wiping users data and if it was never in iCloud in the first place it is totally gone now?! We have always used an NSPersistentCloudKitContainer since we first implemented it years back regardless of if the person enabled iCloud (in our App or not). This was based on statements Apple Engineers made in the past that you could always use NSPersistentCloudKitContainer since it was subclass of nspersistentcontainer and with History on but options set to nil for NOT ALLOWED. But now it seems that users running iOS 18 and who did not allow us to use iCloud (are getting data wiped). It is not clear if they are entirely logged out of iCloud or just have iCloud Drive off or what, but something is different in iOS 18. I really need a way to zero in on what is going on. This is one of those catch 22 situations where by the time we see the issue the data is gone and we do not know what transpired to delete it or if anything actually changed and instead it was some kid of change of behvaior change in iCloud.
4d
Reply to MAJOR Core Data Issues with iOS 18 and sdk - Data Missing for many users?!
Ziqiao are you aware of any behavioral changes in iOS 18 that causes an NSPersistentCloudKitContainer to delete data? In past we were told it could be used in all cases with history on, even if user was not allowing cloudkit. This was true until iOS 18 it seems now if that initializes and user is not using iCloud would it delete data. I thought I was seeing people talking about that and that it does that for security. if That is true that is a huge damn change and which Apple should tell people about?!
4d
Reply to MAJOR Core Data Issues with iOS 18 and sdk - Data Missing for many users?!
Thanks for your response. I will have to see if I can get my hands on a container from a device having the issue and before they start messing with it by saving new data. Is there a way to get the container from a device NOT having Xcode or Development tools if they can connect to a Mac? The issue is definitely real for a small percentage of devices that are mostly overseas in Spain or Italy. Not sure why that is a factor but most are not in USA and not english speaking? I see from Firebase analytics that there are already over 10,000 user running the update on iOS 18 and having the latest build. We are getting a steady stream of 2 or 3 complaints a day. Many of whom DO NOT use iCloud which is also weird. A few using iCloud but most are NOT. Any thoughts on why that might be?
2w
Reply to MAJOR Core Data Issues with iOS 18 and sdk - Data Missing for many users?!
Thank you for your response. The thread I saw about NSFetch being broken in iOS 18 was this one wherein you are the engineer that states that NSFetch is broken back in Sep/Nov 2024 time frame. No Bug Report # was referenced in that thread but perhaps this link will help you find it. This was the first thing I saw when I started researching what might be going on with my App: NSFetch Broken Discussion I don't think our issue is users disabling iCloud right before App launch, unless iOS 18 is somehow doing that during update to OS or App? I didn't think the container moved when you set cloudKitContainerOptions=nil. I thought the store stayed pretty much where it was on the device? But I would like to try your suggestion relative to downloading the store and seeing if data is in it but NSFetch Returns nothing. I am not clear on how to do that. How do we get the store and check if the "store has data" without doing an NSFetch? I was not able to find a way to do this and if the problem is with NSFetch then we are sort of in a Catch 22. Any thoughts or suggestions? I saw your other discussion a few days ago relative to giving users an In-App way to turn on/off Cloudkit. However, another Apple Engineer a while back (see link to forum thread below) stated it was ok to do this by setting cloudKitContainerOptions=nil and that it was relatively harmless?! Has something changed? Based on that forum discussion we implemented what you see in our code. So far it has proved harmless as far as we know and never have we seen any harmful results from it. Here is that thread: OK to diasble/enable iCloud Forum Discussion In past Apple recommended we ask permission to use iCloud. This was quite a few years back. Has this recommendation changed? Given all the users that lose their data because they do not turn it on and then delete the app without a backup and lose the data container, we are thinking to NOT ask and just always enable it. But there are a lot of issues with that. What do we do when the user disables it from iCloud Settings? Of for users that have a full iCloud, typically choked with pictures? Or for users that have a real issue with iCloud (a lot of those in Europe for some reason). But even if I disregarded all that I am not really sure how to transition to this, I guess we could just hide the switch and enable it for all but what happens when their iCloud is full.
2w
Reply to MAJOR Core Data Issues with iOS 18 and sdk - Data Missing for many users?!
Hi, Thanks for your response. I don't think we do any of the things you are concerned about. Here is some of the code I use to set up the CoreData/Cloudkit stack and have been using this for a few years now. Nothing changed here in at least 12 months (I am not exactly a piker in this realm :) : class CoreDataUtil: NSObject { @objc var pc = NSPersistentCloudKitContainer(name:"iphemeris") private lazy var historyRequestQueue = DispatchQueue(label:"history") let coreDataLogSubsystem = "com.iPhemeris.coreData" let coreDataLogger = Logger(subsystem:"com.iPhemeris.coreData", category:"Cloudkit") @objc var useiCloud:Bool = userSettings.bool(forKey:UseIcloudKey) { didSet { userSettings.set(useiCloud, forKey:UseIcloudKey) if(pc.persistentStoreCoordinator.persistentStores.count > 0) { let store = pc.persistentStoreCoordinator.persistentStores[0] do { try pc.persistentStoreCoordinator.remove(store) } catch { coreDataLogger.log("*** CoreDataUtil toggle use iCLoud ON/OFF FAILED: \(error, privacy:.public)") } } self.initCoreDataStack() } } @objc func initCoreDataStack() { coreDataLogger.log("*** Initialize CoreData Stack - Start") guard let description = pc.persistentStoreDescriptions.first else { fatalError("*** CoreDataUtil - could not find persistent store description.") } description.setOption(true as NSNumber, forKey:NSPersistentHistoryTrackingKey) description.setOption(true as NSNumber, forKey:NSPersistentStoreRemoteChangeNotificationPostOptionKey) description.setOption(true as NSNumber, forKey:NSMigratePersistentStoresAutomaticallyOption) description.setOption(true as NSNumber, forKey:NSInferMappingModelAutomaticallyOption) if(useiCloud == true) { coreDataLogger.log("*** User is using iCloud") let cloudKitContainerIdentifier = "iCloud.cribaudo.iphemeris" let options = NSPersistentCloudKitContainerOptions(containerIdentifier:cloudKitContainerIdentifier) description.cloudKitContainerOptions = options } else { coreDataLogger.log("*** User is NOT using iCloud") description.cloudKitContainerOptions = nil } pc.persistentStoreDescriptions.first?.url = storeURL() pc.viewContext.automaticallyMergesChangesFromParent = true pc.loadPersistentStores { _, error in if let error = error as NSError? { self.coreDataLogger.error("*** loadPersistentStore ERROR: \(error, privacy:.public), \(error.userInfo, privacy:.public)") } #if DEBUG // Can be called every time but is needed after model changes //self.initializeCloudKitSchemaForNewModel() #endif self.pc.viewContext.automaticallyMergesChangesFromParent = true // De-dupe old records out of Database. let uuidFixed = NSUbiquitousKeyValueStore.default.object(forKey:CoreDataUUIDNullAndDuplicatesFixed) if(uuidFixed == nil) { self.coreDataLogger.log("*** User does not have uuidFixed Set.") // OLD DeDupe Code - probably can delete soon. // Run UUID De-dupe if it was not yet run for this users account self.findAndfixDuplicateUUID() } else { self.coreDataLogger.log("*** User has uuidFixed Set.") self.deDupeMigratedData() self.findAndfixMissingFirstChar() } // Notify everyone the data is ready self.sendMOCReadyNotificationForPlatform() self.coreDataLogger.log("*** Current CoreData Model Version -> \(self.pc.managedObjectModel.versionIdentifiers.description, privacy:.public)") //self.listAllChartUUID() } // Try to get some error notification of iCloud Storage quota exceeded? NotificationCenter.default.addObserver(self, selector:#selector(processCloudKitErrors), name:NSPersistentCloudKitContainer.eventChangedNotification, object:nil) coreDataLogger.log("*** Initialize CoreData Stack - End") } func initializeCloudKitSchemaForNewModel() { coreDataLogger.log("*** Initialize CloudKit Scheme for New Model - Start") if(!useiCloud) { return } do { // Use the container to initialize the development schema. let options = NSPersistentCloudKitContainerSchemaInitializationOptions() try pc.initializeCloudKitSchema(options:options) } catch { coreDataLogger.error("*** CoreDataUtil Initializing new schema: \(error, privacy:.public)") } coreDataLogger.log("*** Initialize CloudKit Scheme for New Model - End") } func storeOptions() -> [AnyHashable:Any] { return [ NSMigratePersistentStoresAutomaticallyOption:true, NSInferMappingModelAutomaticallyOption:true ] } func storeURL() -> URL { let urls = FileManager.default.urls(for:.documentDirectory, in:.userDomainMask) guard let docURL = urls.last else { fatalError("*** CoreDataUtil RW: StoreURL Error fetching document directory") } let storeURL = docURL.appendingPathComponent("iPhemeris.sqlite") return storeURL } sdds
2w
Reply to MAJOR Core Data Issues with iOS 18 and sdk - Data Missing for many users?!
Hi, but in the original question, I mentioned that on the 1 device we have seen with the issue, we DID open the CoreData store and found 0 (ZERO) Chart. entities where before the update there had been many?! Was that not clear from the explanation associated with the code snippet? Anyway, we did this from within a Utility class we wrote several years ago in Swift to manage initialization of CoreData, de-duping and other housekeeping functions. On the device exhibiting the missing data, we put a break point in a utility function that fetches ALL the Chart entity records and lists a few fields from each. However on this device, the fetch returned nothing and ALL the data appears to be gone?! We saw this using the code snippet example in the original question, where a break point after the fetch showed fetchedCharts to have zero returned objects. This seems to be randomly happening to a growing group of people. But we are seeing NO exceptions of any kind from CoreData. I saw an earlier report in the forum of developers back in Nov. 2024 running into some kind of bug where NSFetchRequest in Swift has a bug and returns no data. Was this issue fixed yet?
2w
Reply to Apple Watch cannot reconnect
My Apple Watch has the same issue. It was connected, then after Xcode 15.3 (released) it stopped talking to Apple Watch device. I unpaired to repair and have never been able to find or see the watch again. Tried toggling developer mode on the watch, no dice. I can connect the watch to Xcode 15.3 on my Laptop, but no longer on mu desktop. If I run: xcrun devicectl list devices the watch is NOT listed as one of the visible devices. All I see are the iPhone and iPad which had also been setup as dev devices?! Why has this issue been ongoing for so long?! I am seeing people reporting this back 8 months now?!
Apr ’24
Reply to Apple Watch cannot reconnect
Damn it Apple! Xcode 15.3 stopped seeing my Apple Watch Ultra 2. So I disconnected thinking I was going repair it and now NADA. I have been crawling all over the net looking for solutions for this. Restarted pretty much everything numerous times. Run Sysdiags, blah blah nothing is working. My iPhone sees it and all of that is working just fine. But Xcode and Devices and Simulators DO NOT see it. Ran the terminal command above and it does not show up. I have the device connected via BOTH bluetooth and WIFI but oddly it (the watch) does NOT see the Mac when searching for Bluetooth devices (system settings are open and on Bluetooth) or anything else for that matter. xcrun devicectl list devices DOES NOT show the watch only my iPhones and iPads. Odd. Devices: Name Hostname Identifier State Model iPad 2024 xx-iPad-2024.coredevice.local C72B3F88-06A9-4CD4-8AFA-49AD478540AB connected iPad Air (5th generation) (iPad13,16) iPhone13 xx-iPhone13.coredevice.local 43A16EBE-911D-4F89-AA42-3DF3B0D21AF9 connected iPhone 13 (iPhone14,5) No watch?! And yet it is right here and talking to my iPhone?!
Apr ’24
Reply to CloudKit - Cannot create or modify field 'CD_nameFirstChar' in record 'CD_Charts' in production schema
The CloudKit Console says the development schema and which has the field nameFirstChar field is indicated as deployed to production. However I DO NOT see it over on the production side. See the images. How is this possible and or what am I missing? The data is syncing just fine on all my devices and perhaps some users ... I think. And I ran this code at various points to deploy development to production: func initializeCloudKitSchemaForNewModel() { coreDataLogger.log("*** Initialize CloudKit Scheme for New Model - Start") if(!useiCloud) { return } do { // Use the container to initialize the development schema. let options = NSPersistentCloudKitContainerSchemaInitializationOptions() try pc.initializeCloudKitSchema(options:options) } catch { coreDataLogger.error("*** CoreDataUtil Initializing new schema: \(error)") } coreDataLogger.log("*** Initialize CloudKit Scheme for New Model - End") }
Apr ’24
Reply to Xcode 14.3.1 Not Updating Obj-C Generated Interface Header
So the only solution I was able to arrive it was to: NOT use the same name for the Swift Class as the old class being refactored into Swift. Have BOTH in the project. Get it to build. Then go back and change all the references to the old class name to new class name. This was the ONLY way to get the ProjectHeader-Swift.h to get built and include the class. This file should probably be built on the fly and dynamically as long as there are no errors in any Swift Classes.
Jul ’23
Reply to Xcode 14.3.1 Not Updating Obj-C Generated Interface Header
How does one get around this circle jerk issue?! The Swift file has NO compile errors that I can see but other things will not build because they are not seeing the full definition of the Swift class and are complaining about the forward Class not having various properties defined in the Swift class. Seriously Apple this is a bit backwards no? Xcode should automatically generate that file as long as there are no build issues in a Swift class.
Jul ’23
Reply to How Force Xcode to ReBuild Bridging Header File
Additional Info. I tried commenting out all references in the Obj-C file to the above class to see if I could get a build that regenerated ProjectName-Swift.h. Didn't work.But when I change Build Setting for "Objective-C Generated Interface Header Name" to: $(SRCROOT)/$(SWIFT_MODULE_NAME)-Swift.h, I get "invalid task ('SwiftMergeGeneratedHeaders .... with mutable output but no other virtual output node?! Any thoughts
Jul ’23
Reply to NSFetchedResultsController use-after-free issues in iOS 16.1
@jamie_sq or anyone have any thoughts regarding this issue related to NSFetch and sectionHeaders? The code in question has worked for years but started failing on iOS 16. After seeing this post and realizing it had something to do with section ordering and seeing that it seems to only happen on devices using foreign languages we looked more carefully at our code and realized that the nameFirstLetter method of our NSManagedObject which is the ONLY Entity in our CoreData database and which returns the string used for sectionNameKeyPath was not properly handling Unicode characters. nameFirstLetter method simply grabs the first character of NAME field on the NSManagedObject. Name is an actual stored field and this method takes the first character and returns it. We improved this to use rangeOfComposedCharacterSequenceAtIndex. That works ok until we tried to do [str localizedUppercaseString] on it. And NOW we see exactly the crash our customers are seeing. -(NSString *)nameFirstLetter { if(self.name != nil) { return [self.name substringWithRange:[self.name rangeOfComposedCharacterSequenceAtIndex:0]]; /* The above works with the issue that sections show up for lower case letters and then again for uppercase. As soon as we do the following the NSFetchResultController CRASHES with the _computeSectionInfo error */ return [[self.name substringWithRange:[self.name rangeOfComposedCharacterSequenceAtIndex:0]] localizedUppercaseString]; } else return @"?"; } We don't understand why this should be a problem given that the NSFetchResultController is initialized to do localizedCaseInsensitiveCompare? This is how we set up the FetchControllers sorts. -(void)initializeFetchedResultsController { // Already inititialized if(_fetchedResultsController != nil) return; // Create and configure a fetch request for Charts NSManagedObjectContext *moc = ((iPhemerisAppDelegate *)[[UIApplication sharedApplication] delegate]).coreDataUtil.pc.viewContext; if(!moc) { NSLog(@"*** SavedChartView MOC NOT READY"); return; } NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"Charts" inManagedObjectContext:moc]; [fetchRequest setEntity:entity]; // Create the sort descriptors array NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)]; NSSortDescriptor *chartTypeDescriptor = [[NSSortDescriptor alloc] initWithKey:@"chartType" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)]; NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:nameDescriptor, chartTypeDescriptor, nil]; [fetchRequest setSortDescriptors:sortDescriptors]; // Create and initialize the fetch results controller. _sectionNameKeyPath = @"nameFirstLetter"; _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:moc sectionNameKeyPath:_sectionNameKeyPath cacheName:nil]; _fetchedResultsController.delegate = self; }
Mar ’23