Post

Replies

Boosts

Views

Activity

Volume purchasing with In-app purchases
Hi, My app is free-to-download but with an in-app purchase to unlock all the features. A user wants to buy 15 copies of the "unlock" IAP and distribute it to his team, using MDM to distribute it easily. I don't believe there is a way to do this through business purchases, is that right? You can only download apps through MDM but not in-app purchases. So what's the best way to do this? Are there any standard solutions? Can I upload a new version of the app that's "paid up-front" but not available through the regular App Store, but only through MDM?
2
0
4.9k
May ’22
Can Intents Extensions access the container app's Application Support directory?
Hi, My Mac app saves it's local database and other important information in the Application Support directory. I want to now create an Intents extension for the app so I can create shortcut actions. When I currently run this, the Application Support directory for the extension is different than for the main application. Is there any way on macOS for the extension to access it's parent applications App Support directory? I know it's not possible in iOS, and you have to use App Groups for this, but I'm wondering about the Mac. BTW, the app is a sandboxed app for the Mac App Store.
1
0
983
Oct ’21
NSApplication's openURLs delegate method not getting called
Hi, I am trying to invoke this NSApplicationDelegate callback from my Mac app, but it's not getting called: - (void)application:(NSApplication *)application openURLs:(NSArray<NSURL *> *)urls I have registered the URL scheme in my Info.plist: <key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleTypeRole</key> <string>Editor</string> <key>CFBundleURLName</key> <string>com.my.testapp</string> <key>CFBundleURLSchemes</key> <array> <string>mytestapp</string> </array> </dict> </array> Now I use a 2nd Mac app to test this out, by invoking the following code: if let url = URL(string: "mytestapp://") {             NSWorkspace.shared.open(url)         } This causes my first app to come to the foreground, and the "applicationDidBecomeActive:(NSNotification *)notification" method gets called, but the "application:(NSApplication *)application openURLs:(NSArray<NSURL *> *)urls" method mentioned above doesn't get invoked, which is what I want. Any ideas about why that might be the case?
1
0
1.4k
Mar ’22
TabularData Framework: crash on opening CSV file
Hi, I am getting a crash report from a user, where they get an application crash when they open a CSV file on their device. I use the standard DataFrame(contentsOfCSVFile: fileURL, options: options) initializer to create a DataFrame, but that's where it's crashing, even though it's inside a try-catch block: public func loadInitialCSVData(withURL fileURL: URL) throws -> DataFrame {      let options = CSVReadingOptions(hasHeaderRow: true, delimiter: ",")       do {          let dataFrame = try DataFrame(contentsOfCSVFile: fileURL, options: options) } catch { // log error here - doesn't get here } This is from the crash report: Exception Type: SIGTRAP Exception Codes: TRAP_BRKPT at 0x21e02be38 Crashed Thread: 0 Thread 0 Crashed: 0 TabularData 0x000000021e02be38 __swift_project_boxed_opaque_existential_1 + 9488 1 TabularData 0x000000021e099d64 __swift_memcpy17_8 + 4612 2 TabularData 0x000000021e099958 __swift_memcpy17_8 + 3576 3 TabularData 0x000000021e09935c __swift_memcpy17_8 + 2044 4 Contacts Journal CRM 0x000000010433f614 Contacts_Journal_CRM.CJCSVHeaderMapper.loadInitialCSVData(withURL: Foundation.URL) throws -> TabularData.DataFrame (CJCSVHeaderMapper.swift:26) 5 Contacts Journal CRM 0x00000001043009d8 (extension in Contacts_Journal_CRM):__C.MacContactsViewController.handleSelectedCSVFileForURL(selectedURL: Foundation.URL) -> () (MacContactsViewControllerExtension.swift:28) 6 Contacts Journal CRM 0x0000000104301e64 @objc (extension in Contacts_Journal_CRM):__C.MacContactsViewController.handleSelectedCSVFileForURL(selectedURL: Foundation.URL) -> () (<compiler-generated>:0) 7 Contacts Journal CRM 0x0000000104222c94 __51-[MacContactsViewController importCSVFileSelected:]_block_invoke (MacContactsViewController.m:954) 8 AppKit 0x00000001bbe8f294 -[NSSavePanel didEndPanelWithReturnCode:] + 84` I can't diagnose the crash, because it doesn't have more information. I don't have access to the CSV file currently either, so I don't know what else I can do to prevent it. What could possibly be causing this crash? Does it not matter that I am also trying to catch the errors it's throwing, or can the app crash because of some internal reasons with the framework?
10
0
3.3k
Jun ’22
Using DataScannerViewController with async stream
Hi, The presentation "Capture Machine Readable Codes and Text with VisionKit" mentions at the end that the DataScannerViewController can be used with an async stream. In the presentation, there is a code snipper for the updateViewAsyncStream method, but it's not really used anywhere. How do utilize this when the DataScannerViewController is active and capture the recognized items? Also there is a sendDidChangeNotification() function sat the end but the compiler complains that it's not in scope. Thanks.
2
0
1.9k
Jul ’22
Replacing [[UIScreen mainScreen] scale] for visionOS
The [[UIScreen mainScreen] scale] API is unavailable for visionOS, but I use it in various places to pass into Apple's drawing APIs ... for e.g.: UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]); and for generating thumbnails: QLThumbnailGenerationRequest *request = [[QLThumbnailGenerationRequest alloc] initWithFileAtURL:fileURL size:size scale:screenScale representationTypes:QLThumbnailGenerationRequestRepresentationTypeThumbnail]; What would be the best way to get the 'scale' factor in this case, when building for visionOS?
1
0
1.6k
Jul ’23
CLLocationManager: getting kCLErrorDenied in widget
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.
2
0
1.7k
Sep ’23
SwiftUI List crash with @FetchRequest and @ObservedObject
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
2
0
1.3k
Mar ’24
UIBarButtonItem: show 'menu' programmatically
Hi, I have a UIBarButtonItem that I create with a UIMenu, and it's added to the navigation bar: self.rightButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd menu: [self createMenuForAddItem]]; self.navigationItem.rightBarButtonItems = @[self.rightButton]; The menu shows fine when a user clicks on the bar button. Now I want to also show this menu programmatically, for e.g if the user opens the app for the 5th time, the menu from the bar button item shows automatically, without the user having to explicitly press the button. How do I achieve this?
Topic: UI Frameworks SubTopic: UIKit Tags:
1
0
820
May ’24
SwiftUI crash only in iOS16.0 and iOS16.1
Hi, I just released a major update to my app that includes a lot of SwiftUI, with a minimum deployment target of iOS15. I've been tracking this one crash that only seems to happen for devices running iOS16 or iOS16.1. I can't track down what is causing this, but this is the crash report I get ... any tips would be helpful. Here's the crash report which might help: Date/Time: 2024-06-13T13:27:41.999Z Launch Time: 2024-06-12T20:47:48Z OS Version: iPhone OS 16.1.1 (20B101) Report Version: 104 Exception Type: SIGTRAP Exception Codes: TRAP_BRKPT at 0x18301cd7c Crashed Thread: 0 Thread 0 Crashed: 0 libswiftCore.dylib 0x000000018301cd7c Swift._assertionFailure(_: Swift.StaticString, _: Swift.String, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Never + 312 1 SwiftUI 0x000000018e0bdc50 OUTLINED_FUNCTION_15 + 1196 2 SwiftUI 0x000000018e0bdef4 OUTLINED_FUNCTION_15 + 1872 3 SwiftUI 0x000000018d4f0508 OUTLINED_FUNCTION_2 + 9436 4 UIKitCore 0x000000018b4200a0 -[UICollectionReusableView _preferredLayoutAttributesFittingAttributes:] + 140 5 UIKitCore 0x000000018b4ac9ec -[UICollectionViewListCell _preferredLayoutAttributesFittingAttributes:] + 236 6 UIKitCore 0x000000018b3806a8 -[UICollectionView _checkForPreferredAttributesInView:originalAttributes:] + 156 7 UIKitCore 0x000000018b5114d4 -[UICollectionView _createPreparedSupplementaryViewForElementOfKind:atIndexPath:withLayoutAttributes:applyAttributes:] + 800 8 UIKitCore 0x000000018ba5abb4 -[UICollectionView _createAndAppendViewAnimationsForExistingAndDeletedAuxiliariesInCurrentUpdate:disappearingAnimations:animationsForOnScreenViews:newSubviewManager:oldVisibleViews:] + 1432 9 UIKitCore 0x000000018b5170dc -[UICollectionView _viewAnimationsForCurrentUpdateWithCollectionViewAnimator:] + 356 10 UIKitCore 0x000000018ba5d2b8 __102-[UICollectionView _updateWithItems:tentativelyForReordering:propertyAnimator:collectionViewAnimator:]_block_invoke.744 + 264 11 UIKitCore 0x000000018b386564 +[UIView(Animation) performWithoutAnimation:] + 72 12 UIKitCore 0x000000018b66873c -[UICollectionView _updateWithItems:tentativelyForReordering:propertyAnimator:collectionViewAnimator:] + 1384 13 UIKitCore 0x000000018b667d58 -[UICollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:animator:collectionViewAnimator:] + 9016 14 UIKitCore 0x000000018b5c57bc -[UICollectionView _performBatchUpdates:completion:invalidationContext:tentativelyForReordering:animator:animationHandler:] + 516 15 SwiftUI 0x000000018d308674 OUTLINED_FUNCTION_7 + 10744 16 SwiftUI 0x000000018cbffef8 OUTLINED_FUNCTION_326 + 7604 17 SwiftUI 0x000000018cd4afa0 OUTLINED_FUNCTION_620 + 720 18 UIKitCore 0x000000018b386564 +[UIView(Animation) performWithoutAnimation:] + 72 19 SwiftUI 0x000000018d3084bc OUTLINED_FUNCTION_7 + 10304 20 SwiftUI 0x000000018cc57234 OUTLINED_FUNCTION_263 + 2444 21 UIKitCore 0x000000018ba5ea38 -[UICollectionView _updateAnimationDidStop:finished:] + 1228 22 UIKitCore 0x000000018ba5e150 __147-[UICollectionView _startViewAnimationsWithContext:oldVisibleViews:reorderedViewAttributesTable:viewAnimator:viewAnimationsCompletedDispatchGroup:]_block_invoke + 32 23 UIKitCore 0x000000018ba7d3f4 __47-[UICollectionViewAnimation startWithAnimator:]_block_invoke_3 + 268 24 UIKitCore 0x000000018c389334 __UIVIEW_IS_EXECUTING_ANIMATION_COMPLETION_BLOCK__ + 32 25 UIKitCore 0x000000018b426808 -[UIViewAnimationBlockDelegate _didEndBlockAnimation:finished:context:] + 632 26 UIKitCore 0x000000018b425764 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 432 27 UIKitCore 0x000000018b424e84 -[UIViewAnimationState animationDidStop:finished:] + 192 28 QuartzCore 0x000000018a838fec CA::Layer::run_animation_callbacks(void*) + 228 29 libdispatch.dylib 0x0000000190771fdc _dispatch_client_callout + 16 30 libdispatch.dylib 0x00000001907807f4 _dispatch_main_queue_drain + 924 31 libdispatch.dylib 0x0000000190780444 _dispatch_main_queue_callback_4CF + 40 32 CoreFoundation 0x00000001892326f8 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12 33 CoreFoundation 0x0000000189214058 __CFRunLoopRun + 2032 34 CoreFoundation 0x0000000189218ed4 CFRunLoopRunSpecific + 608 35 GraphicsServices 0x00000001c2516368 GSEventRunModal + 160 36 UIKitCore 0x000000018b6f73d0 -[UIApplication _run] + 884 37 UIKitCore 0x000000018b6f7034 UIApplicationMain + 336 38 CJournal 0x0000000102ae4060 main (main.m:20) 39 ??? 0x00000001a7880960 0x0 + 0
Topic: UI Frameworks SubTopic: SwiftUI
1
0
819
Jul ’24
CloudKit user 'throttling'
Hi, I have some small amount of users who are receiving a lot of "throttling" error messages from CloudKit when they try to upload / download data from CloudKit. I can see this from the user reports as well as the CloudKit dashboard. It's erratic, unpredictable, and is causing all sorts of bad experience in my app. I would like to understand this more: what causes a particular user to 'throttle' vs others, and what can they do to avoid it? as an e.g if we are uploading 4000 records, having split them up into a 100 CKModifyRecordsOperations with 400 records each ... would that result in some operations getting 'throttled' in the middle of the upload? Would all the operations receive the 'throttled' error message, or only some operations? if I replay all the operations after the recommended timeout, could they also get a 'throttle' response? how do I reproduce something like this in the development environment? With my testing and development so far, I haven't run into such an issue myself. Would love to hear some insight and suggestions about how to handle this.
2
0
817
Jun ’24
iPadOS in iOS18 with new UITabBarController ... UIBarButtonItems disappear
I have an iPad app using the new UITabBarController on iPadOS18, which is suffering from a new issue from the new layout. Within my tabs, I have a UISplitViewController, with a 2 column layout. If I load the app, it works ok, but if I put the app in the background, and then bring it to foreground, the navigation bar buttons and title just disappear from the splitView controller’s primary view controller. Before going to background: After coming back from background: I also get the following layout issues posted in the debugger consoler: Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. ( "<NSLayoutConstraint:0x600002106ee0 UILayoutGuide:0x600003b088c0'TitleView(layout=0x103d18d40)'.trailing <= UILayoutGuide:0x600003b08c40'UIViewLayoutMarginsGuide'.trailing (active)>", "<NSLayoutConstraint:0x600002137520 H:|-(590)-[UILayoutGuide:0x600003b00a80'TabBarGuide(0x103d18810)'](LTR) (active, names: '|':_UINavigationBarContentView:0x103d18810 )>", "<NSLayoutConstraint:0x600002137610 UILayoutGuide:0x600003b00a80'TabBarGuide(0x103d18810)'.width == 0 (active)>", "<NSLayoutConstraint:0x6000021414a0 UILayoutGuide:0x600003b088c0'TitleView(layout=0x103d18d40)'.trailing >= UILayoutGuide:0x600003b00a80'TabBarGuide(0x103d18810)'.trailing (active)>", "<NSLayoutConstraint:0x600002148e10 'UIView-Encapsulated-Layout-Width' _UINavigationBarContentView:0x103d18810.width == 585 (active)>", "<NSLayoutConstraint:0x600002107570 'UIView-rightMargin-guide-constraint' H:[UILayoutGuide:0x600003b08c40'UIViewLayoutMarginsGuide']-(20)-|(LTR) (active, names: '|':_UINavigationBarContentView:0x103d18810 )>" ) Will attempt to recover by breaking constraint <NSLayoutConstraint:0x600002106ee0 UILayoutGuide:0x600003b088c0'TitleView(layout=0x103d18d40)'.trailing <= UILayoutGuide:0x600003b08c40'UIViewLayoutMarginsGuide'.trailing (active)> Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful. I filed a bug report: FB14971801 Is there something I can do avoid this? It'll make my app pretty unusable if the bar button items just disappear every time the user puts the app in the background and then foregrounds the app.
1
0
1.4k
Aug ’24
SwiftUI 'List' performance issue on macOS
Hi, When using SwiftUI ‘List’ with a large number of elements (4000+), I noticed a significant performance issue if extracting the views inside the ‘ForEach’ block into their own subview class. It affects scrolling performance, and using the scroll handle in the scrollbar causes stutters and beachballs. This seems to happen on macOS only ... the same project works fine on iOS. Here's an example of what I mean: List (selection: $multiSelectedContacts) { ForEach(items) { item in // 1. this subview is the problem ... replace it with the contents of the subview, and it works fine PlainContentItemView(item: item) // 2. Uncomment this part for it to work fine (and comment out PlainContentItemView above) /*HStack { if let timestamp = item.timestamp, let itemNumber = item.itemNumber { Text("\(itemNumber) - \(timestamp, formatter: itemFormatter)") } }*/ } } struct PlainContentItemView: View { let item: Item var body: some View { HStack { if let timestamp = item.timestamp, let itemNumber = item.itemNumber { Text("\(itemNumber) - \(timestamp, formatter: itemFormatter)") } } } } Item is a NSManagedObject subclass, and conforms to Identifiable by using the objectID string value. With this, scrolling up and down using the scrolling handle, causes stuttering scrolling and can beachball on my machine (MacBook Pro M1). If I comment out the ‘PlainContentItemView’ and just use the HStack directly (which is what was extracted to ‘PlainContentItemView’), the performance noticeably improves, and I can scroll up and down smoothly. Is this just a bug with SwiftUI, and/or can I do something to improve this?
3
0
679
Mar ’25
SwiftUI: TextField not getting focus changes inside Button
I have a SwiftUI List (on macOS) where I want to display a few TextFields in each row, and observe how the focus changes as an individual text field is selected or unselected. This seems to work fine if I just have the List display a pure TextField in each row, but if I embed the TextField inside a Button view, the focus change notifications stop working. I want the 'button' functionality so that the user can tap anywhere on the row and have the text field activated, instead of tapping exactly on the text field boundary. Here is some code to demonstrate the problem. In the List if you have RowView uncommented out (1), then the focus change notifications work. If you comment that out and uncomment the RowViewWithButton (2), then the button functionality works, but I can't get focus change notifications anymore. Here is the code to reproduce the issue. Interestingly, when I test this on iOS, it works fine in both cases. But I need the solution for macOS. import SwiftUI // test on macOS target struct ContentView: View { @State private var textFields = Array(repeating: "", count: 4) @FocusState private var focusedField: Int? var body: some View { List(0..<4, id: \.self) { index in // 1. works with focus notification changes RowView(index: index, text: $textFields[index], focusedField: $focusedField) // 2. button works, but no focus notifications on text field //RowViewWithButton(index: index, text: $textFields[index], focusedField: $focusedField) } } } struct RowView: View { let index: Int @Binding var text: String @FocusState.Binding var focusedField: Int? var body: some View { HStack { Text("Row \(index + 1):") TextField("", text: $text) .multilineTextAlignment(.leading) .focused($focusedField, equals: index) } .onChange(of: focusedField) { newFocus in if newFocus == index { print("TextField \(index) is in focus") } else { print("TextField \(index) lost focus") } } .padding(.vertical, 4) } } struct RowViewWithButton: View { let index: Int @Binding var text: String @FocusState.Binding var focusedField: Int? var body: some View { Button (action: { print("RowView - button selected at index \(index)") focusedField = index }) { HStack { Text("Row \(index + 1):") TextField("", text: $text) .multilineTextAlignment(.leading) .focused($focusedField, equals: index) } .onChange(of: focusedField) { newFocus in if newFocus == index { print("TextField \(index) is in focus") } else { print("TextField \(index) lost focus") } } .foregroundColor(.primary) } .buttonStyle(BorderlessButtonStyle()) .padding(.vertical, 4) } } #Preview { ContentView() .frame(width: 320, height: 250) }
2
0
306
Mar ’25