Posts

Post not yet marked as solved
2 Replies
355 Views
Hi, I am running into a reproducible SwiftUI List crash when using @FetchRequest based on an @ObservedObject. The crash happens only when deleting the last item in a section. All other deletes and inserts (that I've tested so far) seem to work fine. I'm hoping I can figure out why this happens, and if there is a workaround that I can use. The crash looks something like this: *** Assertion failure in -[SwiftUI.UpdateCoalescingCollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:animator:collectionViewAnimator:], UICollectionView.m:10643 *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to delete item 17 from section 0 which only contains 17 items before the update' The setup: I have a Core Data one-to-many relationship ... in this case, a Contact that has many Notes saved to it. When you select a Contact from a list, it goes to a ContactDetailsView which has some details of the contact, and a list of 'notes' saved to it. struct ContactDetailsView: View { @Environment(\.managedObjectContext) private var viewContext @ObservedObject var contact: Contact // -> making this 'let' works var body: some View { VStack (alignment: .leading) { Text(contact.firstName ?? "") Text(contact.lastName ?? "") NotesListView(contact: contact) Button("Add Test Notes") { let note1 = Notes(context: viewContext) note1.noteMonth = "Feb" note1.noteDetails = "Test1" note1.noteDate = Date() note1.contact = contact try? viewContext.save() } } .padding() } } The NotesListView has a @SectionedFetchRequest (the error is the same if I use a regular @FetchRequest). struct NotesListView: View { @Environment(\.managedObjectContext) private var viewContext @ObservedObject var contact: Contact // -> making this 'let' works @SectionedFetchRequest var sectionNotes: SectionedFetchResults<String, Notes> @State private var selectedNote: Notes? init(contact: Contact) { self.contact = contact let fetchRequest = Notes.fetchRequest() fetchRequest.predicate = NSPredicate(format: "contact == %@", contact) fetchRequest.sortDescriptors = [NSSortDescriptor(key: "noteDate", ascending: true)] _sectionNotes = SectionedFetchRequest(fetchRequest: fetchRequest, sectionIdentifier: \.noteMonth!) } var body: some View { List (selection: $selectedNote){ ForEach(sectionNotes) { section in Section(header: Text(section.id)) { ForEach(section, id: \.self) { note in VStack (alignment: .leading){ if let details = note.noteDetails { Text(details) } } .swipeActions { Button(role: .destructive, action: { delete(note: note) }, label: { Image(systemName: "trash") }) } } } } } } public func delete(note: Notes){ viewContext.delete(note) do{ try viewContext.save() } catch{ print("delete note error = \(error)") } } } Calling the delete method from swipe-to-delete always crashes when the note is the last item on the list. In the ContactDetailsView, and it's child view NotesListView I have marked the 'var contact: Contact' as an @ObservedObject. This is so that changes made to the contact can be reflected in the ContactDetailsView subviews (the name fields here, but there could be more). If I make both of these properties let contact: Contact, I don't get a crash anymore! But then I lose the 'observability' of the Contact, and changes to the name won't reflect on the Text fields. So it seems like something about @ObservedObject and using a List in its subviews is causing this problem, but I'm not sure why. Maybe the @ObservedObject first reloads its relationship and updates the view, and then the FetchRequest also reloads the List, causing a double-delete? But it surprisingly only happens for the last element in the list, and not otherwise. Another option I considered was losing the @FetchRequest and using contact.notes collection to drive the list. But isn't that inefficient compared to a @FetchRequest, especially with sorting and filtering, and loading the list of 1000s of notes? Any suggestions for a work-around are welcome. The full crash looks something like this: *** Assertion failure in -[SwiftUI.UpdateCoalescingCollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:animator:collectionViewAnimator:], UICollectionView.m:10643 *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to delete item 17 from section 0 which only contains 17 items before the update' *** First throw call stack: ( 0 CoreFoundation 0x0000000180491128 __exceptionPreprocess + 172 1 libobjc.A.dylib 0x000000018008412c objc_exception_throw + 56 2 Foundation 0x0000000180d1163c _userInfoForFileAndLine + 0 3 UIKitCore 0x0000000184a57664 -[UICollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:animator:collectionViewAnimator:] + 4020 4 UIKitCore 0x0000000184a62938 -[UICollectionView _performBatchUpdates:completion:invalidationContext:tentativelyForReordering:animator:animationHandler:] + 388 5 SwiftUI 0x00000001c51f0c88 OUTLINED_FUNCTION_249 + 5648 .... 39 TestCoreDataSwiftUISections 0x000000010248c85c $s27TestCoreDataSwiftUISections0abcdE3AppV5$mainyyFZ + 40 40 TestCoreDataSwiftUISections 0x000000010248c998 main + 12 41 dyld 0x0000000102625544 start_sim + 20 42 ??? 0x00000001027560e0 0x0 + 4336214240 43 ??? 0x2103000000000000 0x0 + 2378745028181753856
Posted
by zulfishah.
Last updated
.
Post not yet marked as solved
0 Replies
212 Views
I want to display a list of 'contacts' in my app, loaded from a local Core Data sqlite database. Currently, I use UIKit, and with UITableView's cell reuse, even with 5000+ rows, the memory usage is great ... it loads at about 80MB and stays around that no matter how much I scroll up or down the list. I implemented the same list with SwiftUI List, and the memory usage while scrolling is very different ... the initial load is about the same, but each time I go down the whole list, it adds 20-30MB to the memory usage (according to Xcode). Is this a side-effect of using SwiftUI's List, or am I doing something wrong here? Here's the implementation: struct CJContactsListView: View { @SectionedFetchRequest var sectionContacts: SectionedFetchResults<String, Person> init() { let fetchRequest = Person.allContactsFetchRequest() _sectionContacts = SectionedFetchRequest(fetchRequest: fetchRequest, sectionIdentifier: \.normalizedSectionLetter!, animation: .default) } var body: some View { List { ForEach(sectionContacts) { section in Section(header: Text(section.id)) { ForEach(section) { person in CJContactsListLabelRowView(person: person) } } } } .listStyle(.plain) } } struct CJContactsListLabelRowView: View { @ObservedObject var person: Person var body: some View { HStack (alignment: .center, spacing: 8) { VStack (alignment: .leading){ if let displayName = person.displayName { Text(displayName).font(.headline) } if let companyName = person.companyName { Text(companyName).font(.subheadline).foregroundColor(.secondary) } } } } } extension Person: Identifiable { public var id: String { return self.objectID.uriRepresentation().absoluteString } public static func allContactsFetchRequest() -> NSFetchRequest<Person> { let request = Person.fetchRequest() request.sortDescriptors = Person.makeSortDescriptors() request.predicate = NSPredicate(format: "(isContactArchived == nil || isContactArchived == 0)") request.fetchBatchSize = 100 request.relationshipKeyPathsForPrefetching = ["tags"] return request } } There isn't a visible performance issue in my testing (i.e. I don't see a 'stutter' when scrolling really fast), but the memory profile growing does concern me, especially when this isn't a problem in UIKit. I've tested the "Earthquakes" sample project from Apple and it seems to display the same issue (memory profile grows substantially as the user scrolls down the list). Would love to know if there's a way to avoid this issue.
Posted
by zulfishah.
Last updated
.
Post not yet marked as solved
3 Replies
1.3k Views
Hi, I am testing out an update for my app in macOS Sonoma. I first installed the App Store version of my app on the device running macOS Sonoma, and it ran fine. I then installed an updated version of my app through TestFlight (built with macOS Ventura SDK), but when I run this updated version, I get prompted ”MyApp differs from previously opened versions. Are you sure you want to open it?". Why is this happening? Is this warning only because the app is updated through TestFlight, or do I need to do something to prevent this warning from happening when I update my app through the App Store? I see this mentioned in an Apple security update:: App Sandbox now associates your macOS app with its sandbox container using its code signature. The operating system asks the person using your app to grant permission if it tries to access a sandbox container associated with a different app. For more information, see Accessing files from the macOS App Sandbox. My app is already sandboxed, and I'm not trying to access a different app's sandbox container, just my own. For the TestFlight build, it probably also uses the same Release configuration that the App Store build uses. I might have changed my provisioning profiles recently because they expired. Would that affect this and cause a prompt to be showed? Would love to know more about this prompt and how to avoid it. Thanks.
Posted
by zulfishah.
Last updated
.
Post not yet marked as solved
0 Replies
165 Views
Hi, I am building a List with a list of files saved in my app. I also want this to accept drops of multiple types of files (images, audio, PDFs, Excel, Pages etc) ... basically anything that be dragged-and-dropped from the iOS system or apps like Mail, iCloud Drive etc. I'm trying to find a good way to handle this. The best I've come across is adding the onInsert option to accept UTTypes, like this: List { ... } .onInsert(of: [UTType.data], perform: dropAction) But now I'm not sure how I can load the object that was dropped here. From some examples I've seen, If I registered the UTType.image instead, I could load it in the dropAction handler like this: item.loadObject(ofClass: UIImage.self) { image, _ in DispatchQueue.main.async { print("Image type dropped") } } But how does that work for 'data' types. Or am I supposed to list out all the data types separately?
Posted
by zulfishah.
Last updated
.
Post not yet marked as solved
2 Replies
291 Views
Hi, Is there some limit for how many recordIDs we can fetch in CKFetchRecordsOperation? There doesn't seem to be any batching or cursor support built in to the API. So if I pass in 5000 recordIDs, it'll work fine? Would love to get some confirmation either ways so I can better plan for it. Thanks!
Posted
by zulfishah.
Last updated
.
Post not yet marked as solved
5 Replies
743 Views
I am running into an exception whenever I try to open the app's window in visionOS simulator. The exception error message says: "Thread 1: "Error in UIKit client: window visibility must match its layer visibility!"" This is the same code that runs just fine on iOS where I setup the app's window and tab bar controller in code: - (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Setup the UI - Override point for customization after app launch UIWindowScene *firstScene = (UIWindowScene *) [[[[UIApplication sharedApplication] connectedScenes] allObjects] firstObject]; self.mainWindow = [[UIWindow alloc] initWithWindowScene:firstScene]; self.mainWindow.backgroundColor = [UIColor systemBackgroundColor]; self.tabController = [[UITabBarController alloc] init]; [self.tabController definesPresentationContext]; self.mainWindow.rootViewController = self.tabController; [self.mainWindow makeKeyAndVisible]; // setup the tab bar later The exception comes from the makeKeyAndVisible line. I'm not sure what I need to do differently for a visionOS app to make it work. I'm using Xcode 15.1 Beta 2.
Posted
by zulfishah.
Last updated
.
Post not yet marked as solved
0 Replies
250 Views
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.
Posted
by zulfishah.
Last updated
.
Post not yet marked as solved
0 Replies
336 Views
Hi, I have a few extensions for my iOS app: Share Extension, Widget extensions, Notification Extensions, Today Extension, WatchKit app. My app and all the extensions share data by loading the same Core Data sqlite database from a shared folder. One problem I'm having with this setup is with a Core Data lightweight migration. On updating the app to the new database model, I would like my main app to first make a backup of the database before the migration runs. But one of the app extensions always seems to run before the main app, and ends up performing the lightweight migration on the database file before the main app has a chance to backup the database sqlite file. I can just prevent the lightweight migration from happening when an app extension loads the persistent store (and only do lightweight migrations from the main app), but it might end up in a situation with incompatible formats for the extension, so I'm looking for a sturdier solution. When an app is installed (or an update to the app is installed), is there a way to check and control the order of the extensions that is installed / loaded by the system? That would help control the problem.
Posted
by zulfishah.
Last updated
.
Post not yet marked as solved
0 Replies
245 Views
Hi, My app has been receiving a huge increase in the number of CKHTTPStatus=503 errors over the past couple of months. I created a thread before, and also a Feedback (FB13300807) over a month ago, but I haven't gotten any assistance on this, and am wondering if there is any better way to get the attention of a CloudKit engineer who might be able to help. From my users, I was able to print out the error code and error userInfo in the console: error.code == 15 (the same as CKErrorServerRejectedRequest), UserInfo={ContainerID=, CKHTTPStatus=503, RequestUUID=17C6B9B9-35DD-411B-8AED-7A497075D228, OperationID=5285362CCD2DDB32}}, CKHTTPStatus=503} How can I get this issue addressed? A lot of users are reporting this issue and it's creating a big support burden.
Posted
by zulfishah.
Last updated
.
Post not yet marked as solved
2 Replies
378 Views
Hi, I have a CloudKit based app in production on the App Store for the past 5 years. One feature in the app downloads a lot of records, over a few different recordTypes, from a user's private database using an array of CKQueryOperations (using an NSOperationQueue). This has been working fine for the past few years, and even now works fine for most users, but an increasing number of users are seeing one of the operations in the array fail for CKErrorServerRejectedRequest. This has been happening over a few weeks now, and the customer support is getting burdensome. Asking the user to repeat the feature sometimes fails, and sometimes succeeds, with no obvious reason. This is also happening for operations for recordTypes where there aren't any records in the private database, as well as for recordTypes where there are hundreds of records. I haven't made any changes over the past year that directly impacts this process. Why would this sudden increase be happening and how do I go about analyzing and fixing it? Also, my current code handles this by cancelling all the operations in the operation queue, because the comment I saw in CKError.h for this error says "This is a non-recoverable error". I'm not sure I completely understand what that means ... is the operation non-recoverable (and hence I should retry by creating a new operation), or is the user's private database corrupted, or what? Would be great if I could get some insight / suggestions.
Posted
by zulfishah.
Last updated
.
Post not yet marked as solved
24 Replies
18k Views
Hi, I am getting a linking error when building my app to run against an iOS17 device, using Xcode15. Same project builds and runs fine with Xcode 14 and iOS16. The linking error just says: clang: error: unable to execute command: Segmentation fault: 11 clang: error: linker command failed due to signal (use -v to see invocation) Not sure what I should try to overcome this. I can't run my app on an iOS17 device. It builds, links and runs just fine on a simulator.
Posted
by zulfishah.
Last updated
.
Post not yet marked as solved
3 Replies
4.3k Views
Hi, I need to keep supporting iOS16 for my widgets. I'm having a problem using the iOS17 'containerBackground' API. Ideally I would use a view extension: extension View { func adoptableWidgetBackground(_ color: Color) -> some View { if #available(iOS 17.0, *) { containerBackground(for: .widget) { color } } else { background(color) } } } But this gives an error: Branches have mismatching types 'some View' (result of 'Self.containerBackground(for:alignment:content:)') and 'some View' (result of 'Self.background(_:alignment:)') If I try to use this directly on the 'body' view modifier like this: if #available(iOS 17.0, *) { .containerBackground(for: .widget) { ContainerRelativeShape().fill(Color.init(UIColor.quaternarySystemFill)) } } else { .background(ContainerRelativeShape().fill(Color.init(UIColor.quaternarySystemFill))) } This doesn't work either. Instance member 'containerBackground' cannot be used on type 'View' How do I use this correctly?
Posted
by zulfishah.
Last updated
.
Post marked as solved
2 Replies
690 Views
I am having some problem with accessing the CLLLocationManager location from my widget. It works fine with Xcode 15 running on a iOS17 simulator. But running it on a iOS17 device gives me an error in the delegate: To access the location manager, I have this class: class WidgetLocationManager: NSObject, CLLocationManagerDelegate { var locationManager: CLLocationManager? private var handler: ((CLLocation?) -> Void)? override init() { super.init() DispatchQueue.main.async { print("WidgetLocationManager: init") self.locationManager = CLLocationManager() if self.locationManager!.authorizationStatus == .notDetermined { print("WidgetLocationManager: init - auth status is Undetermined") } else { print("WidgetLocationManager: init - auth status = \(self.locationManager!.authorizationStatus)") } } } func fetchLocation(handler: @escaping (CLLocation?) -> Void) { self.handler = handler self.locationManager = CLLocationManager() self.locationManager!.delegate = self self.locationManager!.requestLocation() } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { if let lastLocation = locations.last { if (CLLocationCoordinate2DIsValid(lastLocation.coordinate) == true && abs(lastLocation.timestamp.timeIntervalSinceNow) < 60 && lastLocation.horizontalAccuracy < 200.0 && lastLocation.horizontalAccuracy > 0.0) { self.handler!(locations.last!) } } } func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { print("WidgetLocationManager: locationManager didFailWithError = \(error)") self.handler!(nil) } } When run on device, I get an error: WidgetLocationManager: locationManager didFailWithError = Error Domain=kCLErrorDomain Code=1 "(null)" Code = 1 in CLError is kCLErrorDenied ("Access to location or ranging has been denied by the user") This is despite getting the following output in the init method: WidgetLocationManager: init - auth status = CLAuthorizationStatus(rawValue: 4) The weird thing is that it works fine in the simulator. On device, I've tried deleting and reinstalling the app a couple of times, restarting the device, making sure the privacy setting is correct etc. Also, on the iOS17 device, when I am in the "Add Widget" page, the location manager runs fine in the preview screen, and shows the 'current location' to the user. But as soon as I add the widget to the home screen, it starts giving me this problem where the location can't be found, and I have to display an error message in the widget. I have the following keys in the Info.plist for the widget: NSLocationAlwaysAndWhenInUseUsageDescription NSLocationWhenInUseUsageDescription NSWidgetWantsLocation The app target also has the following keys in the Info.plist: NSLocationWhenInUseUsageDescription NSLocationAlwaysAndWhenInUseUsageDescription Any idea for what I can try to fix this problem? Thanks.
Posted
by zulfishah.
Last updated
.
Post not yet marked as solved
9 Replies
1.8k Views
Hi, I have an existing Mac app that stores some important values in the keychain. I am working on an update for the app, which was working fine while I was testing with debug builds. But when I build the app for Release and test the update using TestFlight, on trying to access the keychain item, I get prompted by the system: "MyApp wants to use your confidential information stored in "SyncSettingsValue" in your keychain" And the user now has to enter their password and click on "Allow", "Always Allow" or Deny. Obviously this is a really bad experience, and clicking on Deny will stop many features for the user. Why is this happening? I've updated the app 100s of times before and I've never had this problem. I don't believe I'm messing around with any certificate or provisioning profile since the last update, which was only a few weeks ago. How do I find out what is causing the problem here? Or is this a TestFlight issue that won't happen to users when they update through the App Store?
Posted
by zulfishah.
Last updated
.
Post not yet marked as solved
1 Replies
1k Views
When I build my iOS app for the visionOS simulator, it works fine, and it runs in the compatibility mode. When I try to build against the new visionOS SDK, I get build errors related to the bridging header: SimpleList-Bridging-Header.h:5:9: error: 'MyFramework/MyFramework.h' file not found #import <MyFramework/MyFramework.h> ^ 1 error generated. :0: error: failed to emit precompiled header '...DerivedData/CJ-bkylkdabwgxlstdympoknglfewum/Build/Intermediates.noindex/PrecompiledHeaders/SimpleList-Bridging-Header-swift_3HAL1I7NW16O7-clang_3RN0BYG6SZHIS.pch' for bridging header '.../SimpleList/Classes/SimpleList-Bridging-Header.h' 2 errors generated. I don't know why it's not finding my framework for the visionOS SDK, while it works fine for the iOS SDK. The framework is included in the project itself (i.e. it's not an external dependency). Any tips?
Posted
by zulfishah.
Last updated
.