Post

Replies

Boosts

Views

Activity

Custom keyboard while using external keyboard for iPad
Hi! I'm developing a custom keyboard and my user reported that they can't switch to my keyboard while using external original iPad keyboard. Unfortunately, I can't test it on a real device and I can't find a way to test it using a simulator. My questions: Is it possible to simulate this case on a simulator? Is it possible to temporarily show a custom keyboard while using an external keyboard on iPad? I saw in the photos that this keyboard has a globe button, but my user told me that nothing happens when they hold or press hit.
1
0
335
Oct ’24
xcodebuild is very slow unless you set CODE_SIGNING_ALLOWED=NO"
Incremental builds using xcodebuild are very slow, around 3x slower when compared to the same build using Xcode. Recently, I discovered that CODE_SIGNING_ALLOWED=NO" fixed the issue, but of course, I can't then run iOS app. It seems like automatic signing using xcodebuild is somehow broken. Therefore, I think I could set CODE_SIGNING_ALLOWED=NO" and sign it manually later. However, I'm not sure how to do that. I checked what Xcode does and it's: /usr/bin/codesign --force --sign - --entitlements /Users/wkulik/Library/Developer/Xcode/DerivedData/XYZ-hblnhsksxjrctzekqmlevcflnsji/Build/Intermediates.noindex/XYZ.build/Debug-iphonesimulator/XYZ.build/XYZ.app.xcent --timestamp\=none --generate-entitlement-der /Users/wkulik/Library/Developer/Xcode/DerivedData/XYZ-hblnhsksxjrctzekqmlevcflnsji/Build/Products/Debug-iphonesimulator/XYZ.app However, if I run xcodebuild with disabled signing I don't have XYZ.app.xcent required by this command. I also tried: codesign --force --deep --sign "Apple Development: John Snow (XYZ)" /Users/wkulik/Library/Developer/Xcode/DerivedData/XYZ-hblnhsksxjrctzekqmlevcflnsji/Build/Products/Debug-iphonesimulator/XYZ.app but the app immediately terminates (the same way like when unsigned). Could anyone help with that?
1
0
484
Oct ’24
"xcrun xcresulttool get --format json --path" deprecated - what's the alternative?
Hi, I'm using the following command to extract information about the code coverage: xcrun xcresulttool get --format json --path /some/path/to/xcresult However, since Xcode 16 I get: Error: This command is deprecated and will be removed in a future release, --legacy flag is required to use it. But this message doesn't tell us what's the alternative to get the same result. Or are you just getting rid of useful functionality and there is no alternative?
5
2
1.5k
Sep ’24
How to retrieve previously set title for a CKShare?
I create a CKShare and then I set the title: share[CKShare.SystemFieldKey.title] = title I even call: if let cloudStore = coreDatabase.cloudStore { try await persistentContainer.persistUpdatedShare(share, in: cloudStore) } but when I retrieve this share again using persistentContainer.fetchShares(matching: [id]) the title is not set. I even checked CloudKit console and I can't see there title either... How can I retrieve the previously set title for a share?
1
0
375
Aug ’24
How to remove a single record from a CKShare?
It is possible to append a record to a CKShare using NSPersistentCloudKitContainer.share(objects, to: share) but how can I reverse this operation and remove the object from share? The workaround would be to delete and recreate the object, but is there any SDK function to do it right? The more I work with CoreData+CloudKit the more it seems like everything there is a workaround or hack or bug... This SDK is still in Alpha at best.
0
0
326
Aug ’24
CoreData sharing/collaboration feature is broken
On top of unstable CloudKit sync, we've got also extremely unstable sharing/collaboration functionality. I mean, it's quite impressive how easy it is to enable sharing, but this feature should not be released at this point. It feels like using software in the alpha version. Let's take NSPersistentCloudKitContainer.share(_:to:) (https://developer.apple.com/documentation/coredata/nspersistentcloudkitcontainer/3746834-share), the documentation says: Sharing fails if any of the following conditions apply: Any objects in managedObjects, or those the traversal finds, belong to > an existing share record. However, it's wrong... if you pass any object from the existing share, it will return the same share... It never fails in this case. Things are getting even weirder if you experiment a little bit with shares. So let's assume you share a couple of objects: persistentContainer.share([A, B, C, D], to: nil) Now you stop sharing those via UICloudSharingController and you want to share again but just C. So you call: persistentContainer.share([C], to: nil) and surprise, surprise, you get a new share URL, but you share all previously shared objects (A, B, C, D), not as you would have expected only C... On top of that, you keep getting some weird errors like: error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _requestAbortedNotInitialized:](2190): <NSCloudKitMirroringDelegate: 0x3029b84b0> - Never successfully initialized and cannot execute request '<NSCloudKitMirroringExportRequest: 0x30359f1b0>123123123123' due to error: <CKError 0x3018699b0: "Partial Failure" (2/1011); "Failed to modify some record zones"; uuid = 12312312312312; container ID = "iCloud.some.id"; partial errors: { com.apple.coredata.cloudkit.share.123123123123123:__defaultOwner__ = <CKError 0x30186a3d0: "Invalid Arguments" (12/2006); server message = "Only shared zones can be accessed in the shared DB"; op = 12312312312312; uuid = 123123123123> }> Even though the only thing I use is persistentContainer.share and UICloudSharingController(share: share, container: cloudKitContainer) And the cherry on the top, from time to time if you play a little with sharing multiple objects at once, it happens that it randomly wipes out some records from that share... I don't even know where to start reporting issues and if its worth it, because every ticket will be dismissed anyway because "we need thousands of your logs, we require you to do all the job for us".
1
0
449
Aug ’24
The recommended way of handling CoreData+CloudKit errors
What is the recommended way of intercepting and processing errors? As far as I know, there are 4 main areas: iCloud account status - this can be checked and intercepted via notifications exceptions from fetch/execute/save - it can be a simple do..catch, but what exceptions can we expect here, what should be handled, and how? there could be some asynchronous issues with synchronization. How should we intercept them and how should they be handled? issues with iCloud storage - quota exceeded, etc. How to intercept & handle those? I'm trying to achieve production-ready implementation, but there are many pitfalls and hidden issues that are not well documented. Could you provide some advice on how to handle properly all these situations?
3
0
466
Aug ’24
Prevent wiping out all records when user disables iCloud sync for the app
Hello, I'm using NSPersistentCloudKitContainer. If the user disables iCloud sync for my app in the system settings and opens the app, all records are immediately wiped out, even if there are unsynced changes (like records added offline). Disabling iCloud sync doesn't even show any warning, so the user may lose all data (if it's not already synced to Cloud). Is it possible to intercept that the store will be wiped out when the app is launching? I would copy all records to the local storage then to avoid losing data by the user.
1
0
432
Aug ’24
CoreData + CloudKit synchronization is very unstable & unreliable
CloudKit sync is very unstable. Sometimes it just stops syncing for no reason, other times it works almost instantly. The core issue with synchronization is that CoreData relies mostly on two things: silent push notifications, which are by design unreliable and can be throttled user interactions, I noticed that the local database is updated most likely periodically and also based on some app events like entering the foreground. Unfortunately, there is no SDK function that allows us to force sync with CloudKit, which basically prevents us from providing some features to recover if a user encounters problems. After thousands of tests, I finally discovered what was wrong and how to make the synchronization stable. Basically, I noticed that at some point CoreData decides that it won't synchronize data unless you deactivate and activate the application, which is crazy. It's getting even worse if we talk about extensions like the keyboard extension on iOS. The same happens on all platforms. Therefore, knowing that I implemented a trick that happened to work perfectly. The workaround requires to periodically sending an event pretending that the app is going foreground. macOS: var cancellable = Set<AnyCancellable>() // ... Timer.publish(every: 20.0, on: RunLoop.main, in: .common) .autoconnect() .sink { _ in NotificationCenter.default.post(.init(name: NSApplication.willBecomeActiveNotification)) } .store(in: &cancellable) iOS: var cancellable = Set<AnyCancellable>() // ... Timer.publish(every: 20.0, on: RunLoop.main, in: .common) .autoconnect() .sink { _ in NotificationCenter.default.post(.init(name: UIApplication.didBecomeActiveNotification)) } .store(in: &cancellable) After that, everything works perfectly. Pitty that the solution mostly meant for enterprise is so unstable and there is not even a single SDK function to recover from that (force sync). Any plans to fix CoreData+CloudKit? I also created a ticket: #FB14531806.
2
0
760
Jul ’24
CloudKit is not accessible from iOS extension targets
Hi! I'm using CoreData + CloudKit. It works well both on macOS and iOS, however, I can't make it work with extensions (share, action, keyboard). I get Invalid bundle ID for container error: <CKSchedulerActivity: 0x3029f4d20; identifier=com.apple.coredata.cloudkit.activity.export.A65D5B7A-18AA-400A-B25F-F042E46646F6, priority=2, container=iCloud.com.org.app.dev:Sandbox, relatedApplications=( "com.org.App.dev.App-Keyboard" ), xpcActivityCriteriaOverrides={ ActivityGroupName = "com.apple.coredata.cloudkit.App Keyboard.A65D5B7A-18AA-400A-B25F-F042E46646F6"; Delay = 0; Priority = Utility; }> error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _recoverFromPartialError:forStore:inMonitor:](2812): <NSCloudKitMirroringDelegate: 0x303fd82d0>: Error recovery failed because the following fatal errors were found: { "<CKRecordZoneID: 0x300ef9bc0; zoneName=com.apple.coredata.cloudkit.zone, ownerName=__defaultOwner__>" = "<CKError 0x300efa5e0: \"Permission Failure\" (10/2007); server message = \"Invalid bundle ID for container\"; op = xxxxxxx; uuid = zzzzz-xxxxx; container ID = \"iCloud.com.org.app.dev\">"; } I checked everything 10x: profiles, bundle ids, entitlements, etc. I even removed all local provisioning profiles and recreated them, I also tried setting different CloudKit container, but nothing helps. I tested it on a real device. My setup: main app bundle id: com.org.App.dev keyboard bundle id: com.org.App.dev.App-Keyboard action extension bundle id: com.org.App.dev.Action-Extension CloudKit container id: iCloud.com.org.app.dev I keep the CoreData database in the app group container, but I also tried locally and it doesn't really matter. This is how I setup my CoreData: self.persistentContainer = NSPersistentCloudKitContainer(name: "AppCoreModel") persistentContainer.persistentStoreDescriptions = [createCloudStoreDescription()] persistentContainer.loadPersistentStores { [self] _, error in if let error { logError("Could not load Core Data store \(error)") } else { persistentContainer.viewContext.automaticallyMergesChangesFromParent = true persistentContainer.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy logDebug(persistentContainer.persistentStoreDescriptions.first?.url?.absoluteString ?? "") logDebug("Core Data store loaded") } } private func createCloudStoreDescription() -> NSPersistentStoreDescription { let cloudStoreOptions = NSPersistentCloudKitContainerOptions( containerIdentifier: "iCloud.com.org.app.dev" ) cloudStoreOptions.databaseScope = .private let documentsUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: AppConstants.appGroupId)! let cloudStoreDescription = NSPersistentStoreDescription( url: documentsUrl.appendingPathComponent("cloud-database.sqlite") ) cloudStoreDescription.type = NSSQLiteStoreType cloudStoreDescription.cloudKitContainerOptions = cloudStoreOptions cloudStoreDescription.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey) cloudStoreDescription.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey) return cloudStoreDescription } Any help would be highly appreciated. It seems like iOS bug, because everything seems to be configured properly. I even checked app identifiers if containers are properly assigned. Similar issue when using CloudKit directly (unresolved): https://developer.apple.com/forums/thread/665280
3
0
562
Jul ’24
How to ensure fast synchronization between devices using iCloud Database?
For a long time, I've been using just a shared file via iCloud to ensure synchronization between devices. It works very well, everything is synchronized within seconds. However, I started encountering issues with race conditions, especially if there are more than 2 devices updating data. It's easy then to override the database accidentally. That's why I decided to try with the tool that is designed for that: iCloud Database. However, I quickly realized that the performance was extremely low. As I understand, the recommended approach to listen to changes in the database is to create a subscription, and I did that. However, during my tests, I discovered that it can take even 10 or more minutes to get that notification. It's unacceptable, some user could be waiting for new changes on their device. I could of course spam with fetch every 10 seconds (using changeToken), but I'm not sure if it's a good idea. I could also provide manual fetch like pull to refresh or something like that, but automatic synchronization would be much better for the user.
2
0
451
Jul ’24
I can't update macOS Sequoia Beta installed on SSD to the latest release
I installed macOS Sequoia Beta 1 on external SSD and I boot it on my MacBook Pro. I changed my startup disk in Settings to point SSD and I install update via "Software Update". The file is downloaded then my computer restarts and it takes around ~20 seconds to install everything, but once the macOS is started, I see that I've got still Beta 1. I tried also to download the full installer and repeat the process but with the same result. It looks like everything is installed correctly, but once the system is launched, it's still the old macOS version. Any idea how to update the system on my SSD?
0
2
930
Jul ’24