Explore the various UI frameworks available for building app interfaces. Discuss the use cases for different frameworks, share best practices, and get help with specific framework-related questions.

All subtopics
Posts under UI Frameworks topic

Post

Replies

Boosts

Views

Activity

Screenshot preventing
I’d like to know if Apple currently supports any public API or entitlement for blocking in-app screenshots on iOS. If no such API exists, what is the officially recommended approach for App Store apps to prevent or react to screenshots of sensitive content in a banking app? I have tried using a hidden UITextField with isSecureTextEntry = true and observing UIApplication.userDidTakeScreenshotNotification, but these methods do not block the initial screenshot. Could you please advise how to block screenshots in my app?
Topic: UI Frameworks SubTopic: UIKit
6
0
174
Jun ’25
Cannot get drop action to trigger (Xcode 26 beta 3)
I'm unable to find the right combination modifiers to get drag and drop to work using the new .draggable(containerItemID:) and dragContainer(for:in:selection:_:) modifiers. The drag is initiated with the item's ID, the item is requested from the .dragContainer modifier, but the drop closure is never triggered. Minimal repro: struct Item: Identifiable, Codable, Transferable { var id = UUID() var value: String static var transferRepresentation: some TransferRepresentation { CodableRepresentation(contentType: .tab) } } struct DragDrop: View { @State var items: [Item] = [ Item(value: "Hello"), Item(value: "world"), Item(value: "something"), Item(value: "else") ] var body: some View { List(items) { item in HStack { Text(item.value) Spacer() } .contentShape(Rectangle()) .draggable(containerItemID: item.id) .dropDestination(for: Item.self) { items, session in print("Drop: \(items)") } } .dragContainer(for: Item.self) { itemID in print("Drag: \(itemID)") return items.filter { itemID == $0.id } } } } #Preview("Simple") { DragDrop() }
6
0
157
Jul ’25
perspectiveTransform causing large memory spike / app being killed
I have a PDF which contains geocoordinates. I'm extracting out that image with the following code (this is for an iOS application): guard let cgDocument = CGPDFDocument(overlay.pdfUrl as CFURL) else { return } guard let cgPage = cgDocument.page(at: 1) else { return } var boundingRect = self.rect(for: overlay.boundingMapRect) let pdfPageRect = cgPage.getBoxRect(.mediaBox) let renderer = UIGraphicsImageRenderer(size: pdfPageRect.size) var img = renderer.image { ctx in UIColor.white.set() ctx.fill(pdfPageRect) ctx.cgContext.translateBy(x: 0.0, y: pdfPageRect.size.height) ctx.cgContext.scaleBy(x: 1.0, y: -1.0) ctx.cgContext.drawPDFPage(cgPage) } Once I have that image, I then need to adjust it to fit the specific coordinate corners. For that, I'm doing the following using a perspectiveTransform: let ciImg = CIImage(image: img)! let perspectiveTransformFilter = CIFilter.perspectiveTransform() perspectiveTransformFilter.inputImage = ciImg perspectiveTransformFilter.topRight = cartesianForPoint(point: ur, extent: boundingRect) perspectiveTransformFilter.topLeft = cartesianForPoint(point: ul, extent: boundingRect) perspectiveTransformFilter.bottomRight = cartesianForPoint(point: lr, extent: boundingRect) perspectiveTransformFilter.bottomLeft = cartesianForPoint(point: ll, extent: boundingRect) let txImg = perspectiveTransformFilter.outputImage! img = UIImage(ciImage: txImg) The original image is 792 x 612 (a landscape PDF) but the boundingRect covering the coordinates is 25625 x 20030. Obviously when I try to draw the image into that bounding box the app runs out of memory (25625 x 20030 x 4 is around 2GB of memory). What I'm struggling with is - how do I correctly scale this image to fit into the bounding box even though the bounding box is, oh, 10x the resolution of the actual device? There's some key CoreGraphics thing I'm sure I'm missing here.
6
0
284
Sep ’25
Can I tell when my iOS Widget is running on MacOS (when Use IPhone Widgets is on)
I have an iOS Widget that also can load on the Mac when the Use iPhone Widgets setting is turned on on the Mac in Desktop & Dock. I want to use a different url scheme to open video clips from the widget if it is being clicked on iOS or the Mac. I tried using ProcessInfo.processInfo.isiOSAppOnMac but it always thinks it is on iOS. I also tried looking for the user document path to see if it was /var/mobile/ or /Users/. but it always thinks it is /var/mobile. I assume this is as it is not really a catalyst app but a WidgetKit extension from the phone. Is there anyway I can figure out when the widget is running on the mac? Thanks!
6
0
685
Jun ’25
UIDocumentPickerViewController does not allow picking folders on connected servers on iOS26
Hey there, I have an app that allows picking any folder via UIDocumentPickerViewController. Up until iOS18 users were able to pick folders from connected servers (servers connected in the Files app) as well. On iOS26, the picker allows for browsing into the connected servers, but the Select button is greyed out and does nothing when tapped. Is this a known issue? This breaks the whole premise of my file syncronization application.
6
0
276
Nov ’25
iPadOS 26.1: new issue with traitCollection when changing dark mode
Since iPadOS 26.1 I notice a new annoying bug when changing the dark mode option of the system. The appearance of the UI changes, but no longer for view controllers which are presented as Popover. For these view controllers the method "traitCollectionDidChange()" is still called (though sometimes with a very large delay), but checking the traitCollection property of the view controller in there does no longer return the correct appearance (which is probably why the visual appearance of the popover doesn't change anymore). So if the dark mode was just switched on, traitCollectionDidChange() is called, but the "traitCollection.userInterfaceStyle" property still tells me that the system is in normal mode. More concrete, traitCollection.userInterfaceStyle seems to be set correctly only(!) when opening the popover, and while the popover is open, it is never updated anymore when the dark mode changes. This is also visible in the standard Apps of the iPad, like the Apple Maps App: just tap on the "map" icon at the top right to open the "Map mode" view. While the view is open, change the dark mode. All of the Maps App will change its appearance, with the exception of this "Map mode" view. Does anyone know an easy workaround? Or do I really need to manually change the colors for all popup view controllers whenever the dark mode changes? Using dynamic UIColors won't help, because these rely on the "userInterfaceStyle" property, and this is no longer correct. Bugreport: FB20928471
6
4
537
1w
UITabBar Appears During Swipe-Back Gesture on iOS 26 Liquid Glass UI
Hello, While integrating the Liquid Glass UI introduced in iOS 26 into my existing app, I encountered an unexpected issue. My app uses a UITabBarController, where each tab contains a UINavigationController, and the actual content resides in each UIViewController. Typically, I perform navigation using navigationController?.pushViewController(...) and hide the TabBar by setting vc.hidesBottomBarWhenPushed = true when needed. This structure worked perfectly fine prior to iOS 26, and I believe many apps use a similar approach. However, after enabling Liquid Glass UI, a problem occurs. Problem Description From AViewController, I push BViewController with hidesBottomBarWhenPushed = true. BViewController appears, and the TabBar is hidden as expected. When performing a swipe-back gesture, as soon as AViewController becomes visible, the TabBar immediately reappears (likely due to A’s viewWillAppear). The TabBar remains visible for a short moment even if the gesture is canceled — during that time, it is also interactable. Before iOS 26, the TabBar appeared synchronized with AViewController and did not prematurely show during the swipe transition. Tried using the new iOS 18 API: tabBarController?.setTabBarHidden(false, animated: true) It slightly improves the animation behavior, but the issue persists. If hidesBottomBarWhenPushed is now deprecated or discouraged, migrating entirely to setTabBarHidden would require significant refactoring, which is not practical for many existing apps. Is this caused by a misuse of hidesBottomBarWhenPushed, or could this be a regression or design change in iOS 26’s Liquid Glass UI?
Topic: UI Frameworks SubTopic: UIKit Tags:
6
3
922
Dec ’25
TextKit 2 calls NSTextLayoutFragment's draw method too often
The following is verbatim of a feedback report (FB19809442) I submitted, shared here as someone else might be interested to see it (I hate the fact that we can't see each other's feedbacks). On iOS 16, TextKit 2 calls NSTextLayoutFragment's draw(at:in:) method once for the first paragraph, but for every other paragraph, it calls it continuously on every scroll step in the UITextView. (The first paragraph is not cached; its draw is called again when it is about to be displayed again, but then it is again called only once per its lifecycle.) On iOS 17, the behavior is similar; the draw method gets called once for the 1st and 2nd paragraph, and for every other paragraph it again gets called continuously as a user scrolls a UITextView. On iOS 18 (and iOS 26 beta 4), TextKit 2 calls the layout fragment's draw(at:in:) on every scroll step in the UITextView, for all paragraphs. This results in terrible performance. TextKit 2 is promised to bring many performance benefits by utilizing the viewport - a new concept that represents the visible area of a text view, along with a small overscroll. However, having the draw method being constantly called almost negates all the performance benefits that viewport brings. Imagine what could happen if someone needs to add just a bit of logic to that draw method. FPS drops significantly and UX is terribly degraded. I tried optimizing this by only rendering those text line fragments which are in the viewport, by using NSTextViewportLayoutController.viewportBounds and converting NSTextLineFragment.typographicBounds to the viewport-relative coordinate space (i.e. the coordinate space of the UITextView itself). However, this patch only works on iOS 18 where the draw method is called too many times, as the viewport changes. (I may have some other problems in my implementation, but I gave up on improving those, as this can't work reliably on all OS versions since the underlying framework isn't calling the method consistently.) Is this expected? What are our options for improving performance in these areas?
6
0
277
Aug ’25
ios26 NumberPad keyboard issue on iPad
On an iPad running iOS26, there is an issue with the numberPad keyboard I have a UITextField with a keyboard type of .numberPad When I first tap in the field, a new number pad with just numbers (similar to the one that shows up on iPhone) shows up. When I tap again in the field, that number pad goes away. When I tap in the field again, the full keyboard with numbers etc shows up (this is the one that used to always show up pre-iOS26)
Topic: UI Frameworks SubTopic: UIKit
6
2
1.1k
Jan ’26
Question: How to support landscape-only on iPad app after 'Support for all orientations will soon be required' warning
Dear Apple Customer Support, I’m developing a new Swift iPadOS app and I want the app to run in landscape only (portrait disabled). In Xcode, under Target > General > Deployment Info > Device Orientation, if I select only Landscape Left and Landscape Right, the app builds successfully, but during upload/validation I receive this message and the upload is blocked: “Update the Info.plist: Support for all orientations will soon be required.” Could you please advise what the correct/recommended way is to keep an iPad app locked to landscape only while complying with the current App Store upload requirements? Is there a specific Info.plist configuration (e.g., UISupportedInterfaceOrientations~ipad) or another setting that should be used? Thank you,
6
2
560
Mar ’26
Swift Charts: How to prevent scroll position jump when loading more data dynamically
I'm implementing infinite scrolling with Swift Charts where additional historical data loads when scrolling near the beginning of the dataset. However, when new data is loaded, the chart's scroll position jumps unexpectedly. Current behavior: Initially loads 10 data points, displaying the latest 5 When scrolling backwards with only 3 points remaining off-screen, triggers loading of 10 more historical points After loading, the scroll position jumps to the 3rd position of the new dataset instead of maintaining the current view Expected behavior: Scroll position should remain stable when new data is loaded User's current view should not change during data loading Here's my implementation logic using some mock data: import SwiftUI import Charts struct DataPoint: Identifiable { let id = UUID() let date: Date let value: Double } class ChartViewModel: ObservableObject { @Published var dataPoints: [DataPoint] = [] private var isLoading = false init() { loadMoreData() } func loadMoreData() { guard !isLoading else { return } isLoading = true let newData = self.generateDataPoints( endDate: self.dataPoints.first?.date ?? Date(), count: 10 ) self.dataPoints.insert(contentsOf: newData, at: 0) self.isLoading = false print("\(dataPoints.count) data points.") } private func generateDataPoints(endDate: Date, count: Int) -> [DataPoint] { var points: [DataPoint] = [] let calendar = Calendar.current for i in 0..<count { let date = calendar.date( byAdding: .day, value: -i, to: endDate ) ?? endDate let value = Double.random(in: 0...100) points.append(DataPoint(date: date, value: value)) } return points.sorted { $0.date < $1.date } } } struct ScrollableChart: View { @StateObject private var viewModel = ChartViewModel() @State private var scrollPosition: Date @State private var scrollDebounceTask: Task<Void, Never>? init() { self.scrollPosition = .now.addingTimeInterval(-4*24*3600) } var body: some View { Chart(viewModel.dataPoints) { point in BarMark( x: .value("Time", point.date, unit: .day), y: .value("Value", point.value) ) } .chartScrollableAxes(.horizontal) .chartXVisibleDomain(length: 5 * 24 * 3600) .chartScrollPosition(x: $scrollPosition) .chartXScale(domain: .automatic(includesZero: false)) .frame(height: 300) .onChange(of: scrollPosition) { oldPosition, newPosition in scrollDebounceTask?.cancel() scrollDebounceTask = Task { try? await Task.sleep(for: .milliseconds(300)) if !Task.isCancelled { checkAndLoadMoreData(currentPosition: newPosition) } } } } private func checkAndLoadMoreData(currentPosition: Date?) { guard let currentPosition, let earliestDataPoint = viewModel.dataPoints.first?.date else { return } let timeInterval = currentPosition.timeIntervalSince(earliestDataPoint) if timeInterval <= 3 * 24 * 3600 { viewModel.loadMoreData() } } } I attempted to compensate for this jump by adding: scrollPosition = scrollPosition.addingTimeInterval(10 * 24 * 3600) after viewModel.loadMoreData(). However, this caused the chart to jump in the opposite direction by 10 days, rather than maintaining the current position. What's the problem with my code and how to fix it?
6
0
604
Jun ’25
Modal Presentation in UIKit Adds Solid Background in iOS 26
Hello, I have a number of UIViewControllers that are presented as follows: vc.modalPresentationStyle = UIModalPresentationStyle.popover vc.modalTransitionStyle = UIModalTransitionStyle.coverVertical self.present(vc, animated: true, completion: nil) The VC is designed from a Storyboard where I set the 'view' of the VC to have a .clear 'backgroundColor', I have a smaller 'Alert View' added as a subview which is what the user interacts with. In iOS 13 - iOS 18 this would present modally, not take up the entire screen and allow the user to see relevant context from the screen underneath. In iOS 26 Beta 5 and every beta prior the system injects a 'UIDropShadowView' in the View Hierarchy, this view has a solid color backdrop, either white/black depending on light/dark mode. This causes all underlying content to be blocked and essentially forces a full screen modal presentation despite the existing design. I am looking for a way to remove this solid color. I'm not sure if it's intentional or a bug / oversight. I have been able to remove it in a hacky way, I cycle the view hierarchy to find 'UIDropShadowView' and set it's backdrop to transparent. However when you swipe down to partially dismiss the view it turns to Liquid Glass when it is around 75% dismissed and then resets the background color to white/black. I tried creating a custom UIViewControllerTransitioningDelegate so that I could re-implement the existing behaviour but it's incredibly difficult to mimic the partial dismiss swipe down effect on the VC. I have also tried changing my presentation to: vc.modalPresentationStyle = UIModalPresentationStyle.overFullScreen vc.modalTransitionStyle = UIModalTransitionStyle.crossDissolve This works but then the user loses the ability to interactively swipe to dismiss. Any help would be appreciated. Thank you!
Topic: UI Frameworks SubTopic: UIKit Tags:
6
2
475
Aug ’25
iOS 26 regression: Slider does not respect step parameter
In iOS 26, the Slider control no longer respects the step parameter. For example, import SwiftUI struct ContentView: View { @State private var sliderValue: CGFloat = 16 var body: some View { Slider( value: $sliderValue, in: 0...100, step: 5, onEditingChanged: { editing in print(sliderValue) } ) } } In iOS 18, this prints values like 5, 35, 60, 95, etc. In iOS 26.0 (release version), this prints floats that are not rounded to the nearest 5, and the slider does not snap to values ending in 5. Feedback report number: FB20320542
Topic: UI Frameworks SubTopic: SwiftUI
6
4
390
Nov ’25
SwiftUI .destructive alert button in macOS dark mode — poor contrast
Here is a simple view to demonstrate the issue struct ContentView: View { @State private var isPresented = false var body: some View { VStack { Button("Test") { isPresented = true } } .alert("Test", isPresented: $isPresented, actions: { Button("Delete All", role: .destructive) {} }, message: { Text("Are You Sure?") }) .padding() } }``` Which results in ![example alert]("https://aninterestingwebsite.com/forums/content/attachment/c6210120-d82e-4df5-a01a-fc5cb168e1bf" "title=Screenshot 2025-09-08 at 08.57.21.png;width=546;height=442") The destructive button is almost unreadable. WCAG score is 1.4, far below the minimum recommended 4.5. I found [this post](https://stackoverflow.com/q/66448869) on SO going back to Big Sur, but not on this forum. Any known workarounds (except for building my own dialogs, which I am trying to avoid)? Using confirmationDialog instead of alert does not make a difference.
6
0
160
Sep ’25
Animation does not work with List, while works with ScrollView + ForEach
Why there is a working animation with ScrollView + ForEach of items removal, but there is none with List? ScrollView + ForEach: struct ContentView: View { @State var items: [String] = Array(1...5).map(\.description) var body: some View { ScrollView(.vertical) { ForEach(items, id: \.self) { item in Text(String(item)) .frame(maxWidth: .infinity, minHeight: 50) .background(.gray) .onTapGesture { withAnimation(.linear(duration: 0.1)) { items = items.filter { $0 != item } } } } } } } List: struct ContentView: View { @State var items: [String] = Array(1...5).map(\.description) var body: some View { List(items, id: \.self) { item in Text(String(item)) .frame(maxWidth: .infinity, minHeight: 50) .background(.gray) .onTapGesture { withAnimation(.linear(duration: 0.1)) { items = items.filter { $0 != item } } } } } }```
6
1
272
Feb ’26
iOS 26 Beta 3 `safeAreaInsets`
I noticed that trying to access safeAreaInsets from the active window causes an infinite run loop. This issue appeared after updating to Beta 3. Here’s an example of the code: extension UIDevice { var safeAreaInsets: UIEdgeInsets { guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, let window = windowScene.windows.first(where: { $0.isKeyWindow }) else { return .zero } return window.safeAreaInsets } } The return doesn’t happen because it ends up in some kind of recursion.
5
4
676
Jul ’25
Screenshot preventing
I’d like to know if Apple currently supports any public API or entitlement for blocking in-app screenshots on iOS. If no such API exists, what is the officially recommended approach for App Store apps to prevent or react to screenshots of sensitive content in a banking app? I have tried using a hidden UITextField with isSecureTextEntry = true and observing UIApplication.userDidTakeScreenshotNotification, but these methods do not block the initial screenshot. Could you please advise how to block screenshots in my app?
Topic: UI Frameworks SubTopic: UIKit
Replies
6
Boosts
0
Views
174
Activity
Jun ’25
How to avoid the traffic light buttons on iPad
Right now, the traffic light buttons overlapped on my iPad app top corner on windows mode (full screen is fine). How do I properly design my app to avoid the traffic light buttons? Detect that it is iPadOS 26?
Topic: UI Frameworks SubTopic: SwiftUI
Replies
6
Boosts
4
Views
256
Activity
Sep ’25
Advanced App Clip experience URL Status
Hello Team, We have Advanced App Clip Experiences live but we have add App Clip experience URL since long ago but status remains as Received and never changed to Published, can you please help us to fix this issue. Please see attached. Thanks
Replies
6
Boosts
0
Views
1.6k
Activity
Jun ’25
Cannot get drop action to trigger (Xcode 26 beta 3)
I'm unable to find the right combination modifiers to get drag and drop to work using the new .draggable(containerItemID:) and dragContainer(for:in:selection:_:) modifiers. The drag is initiated with the item's ID, the item is requested from the .dragContainer modifier, but the drop closure is never triggered. Minimal repro: struct Item: Identifiable, Codable, Transferable { var id = UUID() var value: String static var transferRepresentation: some TransferRepresentation { CodableRepresentation(contentType: .tab) } } struct DragDrop: View { @State var items: [Item] = [ Item(value: "Hello"), Item(value: "world"), Item(value: "something"), Item(value: "else") ] var body: some View { List(items) { item in HStack { Text(item.value) Spacer() } .contentShape(Rectangle()) .draggable(containerItemID: item.id) .dropDestination(for: Item.self) { items, session in print("Drop: \(items)") } } .dragContainer(for: Item.self) { itemID in print("Drag: \(itemID)") return items.filter { itemID == $0.id } } } } #Preview("Simple") { DragDrop() }
Replies
6
Boosts
0
Views
157
Activity
Jul ’25
perspectiveTransform causing large memory spike / app being killed
I have a PDF which contains geocoordinates. I'm extracting out that image with the following code (this is for an iOS application): guard let cgDocument = CGPDFDocument(overlay.pdfUrl as CFURL) else { return } guard let cgPage = cgDocument.page(at: 1) else { return } var boundingRect = self.rect(for: overlay.boundingMapRect) let pdfPageRect = cgPage.getBoxRect(.mediaBox) let renderer = UIGraphicsImageRenderer(size: pdfPageRect.size) var img = renderer.image { ctx in UIColor.white.set() ctx.fill(pdfPageRect) ctx.cgContext.translateBy(x: 0.0, y: pdfPageRect.size.height) ctx.cgContext.scaleBy(x: 1.0, y: -1.0) ctx.cgContext.drawPDFPage(cgPage) } Once I have that image, I then need to adjust it to fit the specific coordinate corners. For that, I'm doing the following using a perspectiveTransform: let ciImg = CIImage(image: img)! let perspectiveTransformFilter = CIFilter.perspectiveTransform() perspectiveTransformFilter.inputImage = ciImg perspectiveTransformFilter.topRight = cartesianForPoint(point: ur, extent: boundingRect) perspectiveTransformFilter.topLeft = cartesianForPoint(point: ul, extent: boundingRect) perspectiveTransformFilter.bottomRight = cartesianForPoint(point: lr, extent: boundingRect) perspectiveTransformFilter.bottomLeft = cartesianForPoint(point: ll, extent: boundingRect) let txImg = perspectiveTransformFilter.outputImage! img = UIImage(ciImage: txImg) The original image is 792 x 612 (a landscape PDF) but the boundingRect covering the coordinates is 25625 x 20030. Obviously when I try to draw the image into that bounding box the app runs out of memory (25625 x 20030 x 4 is around 2GB of memory). What I'm struggling with is - how do I correctly scale this image to fit into the bounding box even though the bounding box is, oh, 10x the resolution of the actual device? There's some key CoreGraphics thing I'm sure I'm missing here.
Replies
6
Boosts
0
Views
284
Activity
Sep ’25
Can I tell when my iOS Widget is running on MacOS (when Use IPhone Widgets is on)
I have an iOS Widget that also can load on the Mac when the Use iPhone Widgets setting is turned on on the Mac in Desktop & Dock. I want to use a different url scheme to open video clips from the widget if it is being clicked on iOS or the Mac. I tried using ProcessInfo.processInfo.isiOSAppOnMac but it always thinks it is on iOS. I also tried looking for the user document path to see if it was /var/mobile/ or /Users/. but it always thinks it is /var/mobile. I assume this is as it is not really a catalyst app but a WidgetKit extension from the phone. Is there anyway I can figure out when the widget is running on the mac? Thanks!
Replies
6
Boosts
0
Views
685
Activity
Jun ’25
Sidebar Highlight State Issue for Catalyst Apps with UIDesignRequiresCompatibility Flag
Sidebars for mac Catalyst apps running with UIDesignRequiresCompatibility flag render their active items with a white bg tint – resulting in labels and icons being not visible. mac OS Tahoe 26.1 Beta 3 (25B5062e) FB20765036 Example (Apple Developer App):
Replies
6
Boosts
1
Views
510
Activity
Nov ’25
UIDocumentPickerViewController does not allow picking folders on connected servers on iOS26
Hey there, I have an app that allows picking any folder via UIDocumentPickerViewController. Up until iOS18 users were able to pick folders from connected servers (servers connected in the Files app) as well. On iOS26, the picker allows for browsing into the connected servers, but the Select button is greyed out and does nothing when tapped. Is this a known issue? This breaks the whole premise of my file syncronization application.
Replies
6
Boosts
0
Views
276
Activity
Nov ’25
iPadOS 26.1: new issue with traitCollection when changing dark mode
Since iPadOS 26.1 I notice a new annoying bug when changing the dark mode option of the system. The appearance of the UI changes, but no longer for view controllers which are presented as Popover. For these view controllers the method "traitCollectionDidChange()" is still called (though sometimes with a very large delay), but checking the traitCollection property of the view controller in there does no longer return the correct appearance (which is probably why the visual appearance of the popover doesn't change anymore). So if the dark mode was just switched on, traitCollectionDidChange() is called, but the "traitCollection.userInterfaceStyle" property still tells me that the system is in normal mode. More concrete, traitCollection.userInterfaceStyle seems to be set correctly only(!) when opening the popover, and while the popover is open, it is never updated anymore when the dark mode changes. This is also visible in the standard Apps of the iPad, like the Apple Maps App: just tap on the "map" icon at the top right to open the "Map mode" view. While the view is open, change the dark mode. All of the Maps App will change its appearance, with the exception of this "Map mode" view. Does anyone know an easy workaround? Or do I really need to manually change the colors for all popup view controllers whenever the dark mode changes? Using dynamic UIColors won't help, because these rely on the "userInterfaceStyle" property, and this is no longer correct. Bugreport: FB20928471
Replies
6
Boosts
4
Views
537
Activity
1w
UITabBar Appears During Swipe-Back Gesture on iOS 26 Liquid Glass UI
Hello, While integrating the Liquid Glass UI introduced in iOS 26 into my existing app, I encountered an unexpected issue. My app uses a UITabBarController, where each tab contains a UINavigationController, and the actual content resides in each UIViewController. Typically, I perform navigation using navigationController?.pushViewController(...) and hide the TabBar by setting vc.hidesBottomBarWhenPushed = true when needed. This structure worked perfectly fine prior to iOS 26, and I believe many apps use a similar approach. However, after enabling Liquid Glass UI, a problem occurs. Problem Description From AViewController, I push BViewController with hidesBottomBarWhenPushed = true. BViewController appears, and the TabBar is hidden as expected. When performing a swipe-back gesture, as soon as AViewController becomes visible, the TabBar immediately reappears (likely due to A’s viewWillAppear). The TabBar remains visible for a short moment even if the gesture is canceled — during that time, it is also interactable. Before iOS 26, the TabBar appeared synchronized with AViewController and did not prematurely show during the swipe transition. Tried using the new iOS 18 API: tabBarController?.setTabBarHidden(false, animated: true) It slightly improves the animation behavior, but the issue persists. If hidesBottomBarWhenPushed is now deprecated or discouraged, migrating entirely to setTabBarHidden would require significant refactoring, which is not practical for many existing apps. Is this caused by a misuse of hidesBottomBarWhenPushed, or could this be a regression or design change in iOS 26’s Liquid Glass UI?
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
6
Boosts
3
Views
922
Activity
Dec ’25
TextKit 2 calls NSTextLayoutFragment's draw method too often
The following is verbatim of a feedback report (FB19809442) I submitted, shared here as someone else might be interested to see it (I hate the fact that we can't see each other's feedbacks). On iOS 16, TextKit 2 calls NSTextLayoutFragment's draw(at:in:) method once for the first paragraph, but for every other paragraph, it calls it continuously on every scroll step in the UITextView. (The first paragraph is not cached; its draw is called again when it is about to be displayed again, but then it is again called only once per its lifecycle.) On iOS 17, the behavior is similar; the draw method gets called once for the 1st and 2nd paragraph, and for every other paragraph it again gets called continuously as a user scrolls a UITextView. On iOS 18 (and iOS 26 beta 4), TextKit 2 calls the layout fragment's draw(at:in:) on every scroll step in the UITextView, for all paragraphs. This results in terrible performance. TextKit 2 is promised to bring many performance benefits by utilizing the viewport - a new concept that represents the visible area of a text view, along with a small overscroll. However, having the draw method being constantly called almost negates all the performance benefits that viewport brings. Imagine what could happen if someone needs to add just a bit of logic to that draw method. FPS drops significantly and UX is terribly degraded. I tried optimizing this by only rendering those text line fragments which are in the viewport, by using NSTextViewportLayoutController.viewportBounds and converting NSTextLineFragment.typographicBounds to the viewport-relative coordinate space (i.e. the coordinate space of the UITextView itself). However, this patch only works on iOS 18 where the draw method is called too many times, as the viewport changes. (I may have some other problems in my implementation, but I gave up on improving those, as this can't work reliably on all OS versions since the underlying framework isn't calling the method consistently.) Is this expected? What are our options for improving performance in these areas?
Replies
6
Boosts
0
Views
277
Activity
Aug ’25
ios26 NumberPad keyboard issue on iPad
On an iPad running iOS26, there is an issue with the numberPad keyboard I have a UITextField with a keyboard type of .numberPad When I first tap in the field, a new number pad with just numbers (similar to the one that shows up on iPhone) shows up. When I tap again in the field, that number pad goes away. When I tap in the field again, the full keyboard with numbers etc shows up (this is the one that used to always show up pre-iOS26)
Topic: UI Frameworks SubTopic: UIKit
Replies
6
Boosts
2
Views
1.1k
Activity
Jan ’26
Question: How to support landscape-only on iPad app after 'Support for all orientations will soon be required' warning
Dear Apple Customer Support, I’m developing a new Swift iPadOS app and I want the app to run in landscape only (portrait disabled). In Xcode, under Target &gt; General &gt; Deployment Info &gt; Device Orientation, if I select only Landscape Left and Landscape Right, the app builds successfully, but during upload/validation I receive this message and the upload is blocked: “Update the Info.plist: Support for all orientations will soon be required.” Could you please advise what the correct/recommended way is to keep an iPad app locked to landscape only while complying with the current App Store upload requirements? Is there a specific Info.plist configuration (e.g., UISupportedInterfaceOrientations~ipad) or another setting that should be used? Thank you,
Replies
6
Boosts
2
Views
560
Activity
Mar ’26
Swift Charts: How to prevent scroll position jump when loading more data dynamically
I'm implementing infinite scrolling with Swift Charts where additional historical data loads when scrolling near the beginning of the dataset. However, when new data is loaded, the chart's scroll position jumps unexpectedly. Current behavior: Initially loads 10 data points, displaying the latest 5 When scrolling backwards with only 3 points remaining off-screen, triggers loading of 10 more historical points After loading, the scroll position jumps to the 3rd position of the new dataset instead of maintaining the current view Expected behavior: Scroll position should remain stable when new data is loaded User's current view should not change during data loading Here's my implementation logic using some mock data: import SwiftUI import Charts struct DataPoint: Identifiable { let id = UUID() let date: Date let value: Double } class ChartViewModel: ObservableObject { @Published var dataPoints: [DataPoint] = [] private var isLoading = false init() { loadMoreData() } func loadMoreData() { guard !isLoading else { return } isLoading = true let newData = self.generateDataPoints( endDate: self.dataPoints.first?.date ?? Date(), count: 10 ) self.dataPoints.insert(contentsOf: newData, at: 0) self.isLoading = false print("\(dataPoints.count) data points.") } private func generateDataPoints(endDate: Date, count: Int) -> [DataPoint] { var points: [DataPoint] = [] let calendar = Calendar.current for i in 0..<count { let date = calendar.date( byAdding: .day, value: -i, to: endDate ) ?? endDate let value = Double.random(in: 0...100) points.append(DataPoint(date: date, value: value)) } return points.sorted { $0.date < $1.date } } } struct ScrollableChart: View { @StateObject private var viewModel = ChartViewModel() @State private var scrollPosition: Date @State private var scrollDebounceTask: Task<Void, Never>? init() { self.scrollPosition = .now.addingTimeInterval(-4*24*3600) } var body: some View { Chart(viewModel.dataPoints) { point in BarMark( x: .value("Time", point.date, unit: .day), y: .value("Value", point.value) ) } .chartScrollableAxes(.horizontal) .chartXVisibleDomain(length: 5 * 24 * 3600) .chartScrollPosition(x: $scrollPosition) .chartXScale(domain: .automatic(includesZero: false)) .frame(height: 300) .onChange(of: scrollPosition) { oldPosition, newPosition in scrollDebounceTask?.cancel() scrollDebounceTask = Task { try? await Task.sleep(for: .milliseconds(300)) if !Task.isCancelled { checkAndLoadMoreData(currentPosition: newPosition) } } } } private func checkAndLoadMoreData(currentPosition: Date?) { guard let currentPosition, let earliestDataPoint = viewModel.dataPoints.first?.date else { return } let timeInterval = currentPosition.timeIntervalSince(earliestDataPoint) if timeInterval <= 3 * 24 * 3600 { viewModel.loadMoreData() } } } I attempted to compensate for this jump by adding: scrollPosition = scrollPosition.addingTimeInterval(10 * 24 * 3600) after viewModel.loadMoreData(). However, this caused the chart to jump in the opposite direction by 10 days, rather than maintaining the current position. What's the problem with my code and how to fix it?
Replies
6
Boosts
0
Views
604
Activity
Jun ’25
QLThumbnailGenerator macOS 26.4 No Longer Honors Users 'Folder Color' Preference When Making Icons for Folders
I use QLThumbnailGenerator to generate icons. After updating to macOS Tahoe 26.4 the folder color preference of the user is no longer respected. It just makes the icon default 'light blue.'
Replies
6
Boosts
0
Views
140
Activity
1w
Modal Presentation in UIKit Adds Solid Background in iOS 26
Hello, I have a number of UIViewControllers that are presented as follows: vc.modalPresentationStyle = UIModalPresentationStyle.popover vc.modalTransitionStyle = UIModalTransitionStyle.coverVertical self.present(vc, animated: true, completion: nil) The VC is designed from a Storyboard where I set the 'view' of the VC to have a .clear 'backgroundColor', I have a smaller 'Alert View' added as a subview which is what the user interacts with. In iOS 13 - iOS 18 this would present modally, not take up the entire screen and allow the user to see relevant context from the screen underneath. In iOS 26 Beta 5 and every beta prior the system injects a 'UIDropShadowView' in the View Hierarchy, this view has a solid color backdrop, either white/black depending on light/dark mode. This causes all underlying content to be blocked and essentially forces a full screen modal presentation despite the existing design. I am looking for a way to remove this solid color. I'm not sure if it's intentional or a bug / oversight. I have been able to remove it in a hacky way, I cycle the view hierarchy to find 'UIDropShadowView' and set it's backdrop to transparent. However when you swipe down to partially dismiss the view it turns to Liquid Glass when it is around 75% dismissed and then resets the background color to white/black. I tried creating a custom UIViewControllerTransitioningDelegate so that I could re-implement the existing behaviour but it's incredibly difficult to mimic the partial dismiss swipe down effect on the VC. I have also tried changing my presentation to: vc.modalPresentationStyle = UIModalPresentationStyle.overFullScreen vc.modalTransitionStyle = UIModalTransitionStyle.crossDissolve This works but then the user loses the ability to interactively swipe to dismiss. Any help would be appreciated. Thank you!
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
6
Boosts
2
Views
475
Activity
Aug ’25
iOS 26 regression: Slider does not respect step parameter
In iOS 26, the Slider control no longer respects the step parameter. For example, import SwiftUI struct ContentView: View { @State private var sliderValue: CGFloat = 16 var body: some View { Slider( value: $sliderValue, in: 0...100, step: 5, onEditingChanged: { editing in print(sliderValue) } ) } } In iOS 18, this prints values like 5, 35, 60, 95, etc. In iOS 26.0 (release version), this prints floats that are not rounded to the nearest 5, and the slider does not snap to values ending in 5. Feedback report number: FB20320542
Topic: UI Frameworks SubTopic: SwiftUI
Replies
6
Boosts
4
Views
390
Activity
Nov ’25
SwiftUI .destructive alert button in macOS dark mode — poor contrast
Here is a simple view to demonstrate the issue struct ContentView: View { @State private var isPresented = false var body: some View { VStack { Button("Test") { isPresented = true } } .alert("Test", isPresented: $isPresented, actions: { Button("Delete All", role: .destructive) {} }, message: { Text("Are You Sure?") }) .padding() } }``` Which results in ![example alert]("https://aninterestingwebsite.com/forums/content/attachment/c6210120-d82e-4df5-a01a-fc5cb168e1bf" "title=Screenshot 2025-09-08 at 08.57.21.png;width=546;height=442") The destructive button is almost unreadable. WCAG score is 1.4, far below the minimum recommended 4.5. I found [this post](https://stackoverflow.com/q/66448869) on SO going back to Big Sur, but not on this forum. Any known workarounds (except for building my own dialogs, which I am trying to avoid)? Using confirmationDialog instead of alert does not make a difference.
Replies
6
Boosts
0
Views
160
Activity
Sep ’25
Animation does not work with List, while works with ScrollView + ForEach
Why there is a working animation with ScrollView + ForEach of items removal, but there is none with List? ScrollView + ForEach: struct ContentView: View { @State var items: [String] = Array(1...5).map(\.description) var body: some View { ScrollView(.vertical) { ForEach(items, id: \.self) { item in Text(String(item)) .frame(maxWidth: .infinity, minHeight: 50) .background(.gray) .onTapGesture { withAnimation(.linear(duration: 0.1)) { items = items.filter { $0 != item } } } } } } } List: struct ContentView: View { @State var items: [String] = Array(1...5).map(\.description) var body: some View { List(items, id: \.self) { item in Text(String(item)) .frame(maxWidth: .infinity, minHeight: 50) .background(.gray) .onTapGesture { withAnimation(.linear(duration: 0.1)) { items = items.filter { $0 != item } } } } } }```
Replies
6
Boosts
1
Views
272
Activity
Feb ’26
iOS 26 Beta 3 `safeAreaInsets`
I noticed that trying to access safeAreaInsets from the active window causes an infinite run loop. This issue appeared after updating to Beta 3. Here’s an example of the code: extension UIDevice { var safeAreaInsets: UIEdgeInsets { guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, let window = windowScene.windows.first(where: { $0.isKeyWindow }) else { return .zero } return window.safeAreaInsets } } The return doesn’t happen because it ends up in some kind of recursion.
Replies
5
Boosts
4
Views
676
Activity
Jul ’25