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

UINavigationBarAppearance background does not extend to the top edge on iPhone Duo
Environment Xcode 27.1 iOS 27.1 iPhone Duo simulator UIKit app built with the iOS 27.1 SDK Issue On iPhone Duo, the background of a system-managed UINavigationBar does not extend completely to the top edge of the window. The navigation bar is configured using UINavigationBarAppearance with an opaque blue background. However, a horizontal white strip remains above the blue navigation bar. I also post a feedback: FB24859353 Questions Is this expected behavior on iPhone Duo? What is the recommended way to style this top region? Should apps add a custom background underlay outside the UINavigationBar bounds? Could this be an iOS 27.1 or iPhone Duo simulator issue? Minimal reproduction code: import UIKit final class DemoTabBarController: UITabBarController { override func viewDidLoad() { super.viewDidLoad() viewControllers = NavigationBarStyle.allCases.map { style in let content = DiagnosticsViewController(style: style) let navigationController = UINavigationController(rootViewController: content) navigationController.tabBarItem = UITabBarItem( title: style.title, image: UIImage(systemName: style.symbolName), selectedImage: nil ) style.apply(to: navigationController.navigationBar) return navigationController } } } enum NavigationBarStyle: CaseIterable { case systemDefault case appearance case legacy var title: String { switch self { case .systemDefault: return "Default" case .appearance: return "Appearance" case .legacy: return "Legacy" } } var symbolName: String { switch self { case .systemDefault: return "iphone" case .appearance: return "paintbrush" case .legacy: return "clock.arrow.circlepath" } } func apply(to navigationBar: UINavigationBar) { switch self { case .systemDefault: break case .appearance: let appearance = UINavigationBarAppearance() appearance.configureWithOpaqueBackground() appearance.backgroundColor = .demoBlue appearance.shadowColor = nil appearance.titleTextAttributes = [.foregroundColor: UIColor.white] navigationBar.tintColor = .white navigationBar.standardAppearance = appearance navigationBar.compactAppearance = appearance navigationBar.scrollEdgeAppearance = appearance case .legacy: navigationBar.tintColor = .white navigationBar.barTintColor = .demoBlue navigationBar.backgroundColor = .demoBlue navigationBar.setBackgroundImage(Self.solidImage(color: .demoBlue), for: .default) navigationBar.shadowImage = UIImage() navigationBar.isTranslucent = false navigationBar.titleTextAttributes = [.foregroundColor: UIColor.white] } } private static func solidImage(color: UIColor) -> UIImage { return UIGraphicsImageRenderer(size: CGSize(width: 1, height: 1)).image { context in color.setFill() context.fill(CGRect(x: 0, y: 0, width: 1, height: 1)) } } } private extension UIColor { static let demoBlue = UIColor(red: 0.0, green: 0.46, blue: 0.70, alpha: 1.0) }
4
2
916
1w
NSScrollView: Overriding "scrollWheel(with:)" can cause a never-ending live scroll
Overview I'm developing an app that depends on NSScrollView to implement a scrollable and zoomable canvas. I need to override NSScrollView.scrollWheel(with:) to implement Option-zooming (holding Option while scrolling up/down to zoom in/out). I've found that simply adding these three lines of code in my NSScrollView subclass: override func scrollWheel(with event: NSEvent) { super.scrollWheel(with: event) }is enough to cause a live scroll to never end, and NSScrollView.didEndLiveScrollNotification to never fire. My app depends on that notification firing so that it can disable some interactions during a live scroll. Furthermore, while the NSScrollView is "stuck" in the live scroll, it's not possible to perform a live magnify. There are also some other effects, including elevated CPU usage and persistent scroll indicators. The issue is occurring with Xcode 27.1 (27A9275) and macOS 27.2 (26B123). I have modified the macOS App project template to showcase the issue. The sample project, along with a screen recording of the issue, can be downloaded from here: https://drive.google.com/drive/folders/1F5sF2NA230NkGbQdLfbV6vM1XmfY1-uT?usp=sharing I hope that Apple can fix this issue soon, as it's a frustrating user experience when the canvas gets stuck while scrolling. I've already filed this in Feedback Assistant under FB25362729. Steps to Reproduce To recreate the issue, follow these steps: Download and extract the "Xcode Project.zip" file from the link above. Open the extracted "NSScrollViewTest" project in Xcode. Build and run the "NSScrollViewTest" app. Scroll all the way to the right edge of the gray canvas using the horizontal scroll gesture on Magic Trackpad. If you comment out lines 8–10 of ScrollView.swift, the issue goes away. The "Issue Recording.mov" file from the link above provides a detailed video of how to recreate the issue.
Topic: UI Frameworks SubTopic: AppKit
11
0
736
1w
SplitViewController removed the ability to have a side menu on iPhone
Sometime pre-iOS 26 it was possible to use a SplitViewController so that on iPhone you saw the master as a side menu (e.g. hamburger), and the detail full screen. While on iPad you would see the master displayed in a sidebar that could be closed, with the detail fullscreen. This has changed, using a SplitViewController on iPhone now forces you into having 2 fullscreen screens, with a push/pop layout and a back button. In situations where you want the detail screen to open first, this results in users opening the app to find a back button already presented, despite having not navigated anywhere. They must "return" to a screen they never saw. I really despise this layout and find it to be quite a UX issue. But given the new iPhone Duo, using the SplitViewController is now one of the easiest ways to maintain the necessary responsiveness needed, forcing us to accept this behaviour on regular iPhones. Can we PLEASE get the old functionality back, where we can explicitly state on iPhone that the master will always be displayed as a menu?
1
0
471
1w
UIKIt, iOS 27, UIDocumentPickerViewController(forExporting: [fileURL])
My App saves files using the UIDocumentPickerViewController. This works from iOS 17 to 26. Usually, you have a file with a given name in your sandbox, which you can then export via the pickerVC. In the pickerVC you change the name. In iOS 27 the file name is greyed-out and you can't change it here. The file can be exported only with the pre-given name. Is this a new behaviour or bug in iOS 27?
Topic: UI Frameworks SubTopic: UIKit
1
0
122
1w
Age Range Functionality in MacOS 27.2 no handle?
I have a running implementation for an iOS Application which is using AgeRange. It was running very well on Mac OS below 27 and was getting the results. It is still working on iOS 27.2 but now in MacOS 27.2 with the same code base I'm getting an } catch AgeRangeService.Error.notAvailable { NSLog("[AgeRangeDeclaration] Handle not available error")Is there a change for MacOS 27 which has to be implemented or do I have to configure something else?
Topic: UI Frameworks SubTopic: General
0
0
107
1w
Workaround for NSTableView bugs introduced in macOS 27
MacOS 27 (or perhaps 26, I never used it) introduces two bugs in NSTableView (and delegate). It's always a pleasure when you find that your app no longer works properly. First, when the delegate responds to tableView:pasteboardWriterForRow:, no row can be selected by click & drag (even if the method returns nil). Which mean that clicking and dragging the mouse on rows that are not draggable simply does nothing (no selection), which is a frustrating user experience, especially considering that the same action selects rows on macOS 15. The second bug is that tableView.verticalMotionCanBeginDrag = NO is simply ignored. It doesn’t work. So, a click followed by an immediate vertical drag drags the clicked row instead of selecting rows if tableView:pasteboardWriterForRow: does not return nil. Again, it did select rows on macOS 15. That's what verticalMotionCanBeginDrag = NO is for. To work around the first bug, I implement respondsToSelector: in the delegate to return NO when the selector is tableView:pasteboardWriterForRow: and the clicked row is not draggable. This solution is not elegant, as theclickedRow property of the tableview always returns -1 when the method is called. Which means I need to determine the clicked row by other means (using the mouse location and stuff). (This solution should in principle allow working around the second bug, but I haven’t implemented it yet. It would require determining the delay between the click and the drag and the direction of the drag). So my question is: does anyone see a better workaround for these bugs?
Topic: UI Frameworks SubTopic: AppKit
3
0
272
1w
NavigationSplitView Binding to NavigationSplitViewColumn reset with every NavigationStack path change
I try to create a Navigation that works on iPhone, iPhone Duo and iPad. NavigationSplitView collapses for compact form factors and makes iPhone Duo support much simpler. The Problem is the semantic of the collapse. Switch from detail to sidebar on compact is not a 'back' action in my case. It should have my choosen Icon and has a meaning. So i wanted to control this using the NavigationSpliViewColumn Binding. This does work forward and backward as long as no NavigationStack was used before. But it stops working when you return to the detail root from a Navigation-Action. I left the Backbutton visible so you can test, that it continues to work, when no Navigation-Action preceeded the switch. Here is my Code: import SwiftUI @Observable final class Compass { var path: [Route] init() { self.path = [] } } enum Route: Hashable { case goal } struct ContentView: View { @Environment(\.horizontalSizeClass) private var hsize @State private var compass: Compass = Compass() @State var column: NavigationSplitViewColumn = .detail var body: some View { NavigationSplitView(preferredCompactColumn: $column) { OverviewScreen(column: $column) } detail: { TodayScreen() .toolbar { ToolbarItem(placement: .topBarLeading) { Button("overview", systemImage: "calendar") { self.column = .sidebar } } } } .environment(compass) .onChange(of: column) { old, new in print("column:", old, "→", new) } } } struct OverviewScreen: View { @Binding var column: NavigationSplitViewColumn @Environment(Compass.self) var compass var body: some View { @Bindable var compass = self.compass ScrollView { Text("Overview") .font(.largeTitle) .fontWeight(.heavy) Button("Switch") { self.column = .detail } } } } struct TodayScreen: View { @Environment(Compass.self) var compass var body: some View { @Bindable var compass = self.compass NavigationStack(path: $compass.path) { ScrollView { Text("Today") .font(.largeTitle) .fontWeight(.heavy) Button("Goals programtically", systemImage: "flag.fill") { self.compass.path = [.goal] } NavigationLink(value: Route.goal) { Label("Goal Link", systemImage: "flag.fill") } } .navigationDestination(for: Route.self, destination: self.screen) } } @ContentBuilder func screen(for route: Route) -> some View { switch route { case .goal: Text("Goals") } } } #Preview { ContentView() }This seems unexpected behaviour. If you ask AI the mental model is NavigationSplitViewColumn represents which column is currently visible for the user. That model would be wrong. Also i can't understand why a NavigationStack has to change the Binding? What am i missing here? Is my idea of the programmatic switch not supported? There are other ways to push from compact to your detail column again, but they all have trade-offs or run into other problems. I would appreciate any help here. AI has not understood this and only does surface level work arounds that fix nothing.
0
0
60
1w
NSSegmentedControl style ineffective.
I'm not sure if it's something wrong with my XCode install (Version 27.1, macOS 27.2) or what, because such a serious issue should be mentioned already... Basically, building my objC app with the latest XCode makes the NSSegmentedControl style ineffective. Likewise, changing the style in the attribute of the control in interface builder has no visible effect on the preview either. Changing the style in code or in IB has no effect. The control appears stuck with a style that implements a blue background for the selected segment (some default style I guess). I tried with a minimalistic app that includes only one window and the control. The issue is still present. Any suggestion? Am I the only one experiencing this?
Topic: UI Frameworks SubTopic: AppKit
8
0
513
1w
NSScrollView scrolling hitch
When scrolling a basic NSScrollView there seems to be a sudden jump after each flick. Scrolling does not appear smooth and is disorientating. A scroll jump seems to happen directly after letting go of a scroll flick using a trackpad/mouse. Right at that moment the scroll turns into a momentum scroll, slowly decreasing the speed. But the first frame after the gesture the content jumps forward, more than what is expected. Observations: Counterintuitively, scrolling appears to be smoother when disabling NSScrollView.isCompatibleWithResponsiveScrolling. If disabled using a custom NSScrollView subclass there is no large jump anymore. Scrolling also appears to be smoother using a SwiftUI ScrollView. I assume that has the same behaviour as a disabled isCompatibleWithResponsiveScrolling Ironically a WKWebView scrolls much smoother. No sudden jump is observable. It also seems to scroll with faster acceleration, but the individual frames do appear smoother. Why is this better than a native NSScrollView? Elastic scrolling at the bounds of the scroll view also appears much smoother for WKWebViews. When pulling to refresh there is a jump for NSScrollView/SwiftUI, but not for WKWebView. When using an NSScrollView with isCompatibleWithResponsiveScrolling disabled, scrolling appears just as smooth as WKWebView on macOS 13 Ventura and below. On macOS 14 Sonoma scrolling behaviour is suddenly different. Please see a sample project with 4 different scroll views side by side: https://github.com/floorish/ScrollTest Screen recordings show the sudden jumps when scrolling and when elastic scrolling. Tested on Intel & Arm Macs, macOS 11 Big Sur through 15 Sequoia, built with Xcode 16. Should isCompatibleWithResponsiveScrolling be disabled on Sonoma+? Are there any drawbacks? There is also no overdraw anymore since Monterey, as described in https://developer.apple.com/library/archive/releasenotes/AppKit/RN-AppKitOlderNotes/#10_9Scrolling Even with responsive scrolling disabled, why is WKWebView scrolling much smoother than NSScrollView?
Topic: UI Frameworks SubTopic: AppKit Tags:
9
3
1.4k
1w
What pattern to use for an iPhone Tabview app
I have an iPhone tab view application that has not been designed for iPad, and I am aiming to add a left-hand bar that summarises some content and keeps visible what is normally a sheet. What pattern would work best for this? At present, I pass the view to another view with a navigation stack containing an arrangement view with the previous view and then the sidebar as a secondary view within it—would that be the appropriate approach?
Topic: UI Frameworks SubTopic: SwiftUI
3
0
434
1w
State Restoration no longer works in a Mac Catalyst based app when run on macOS 27.x
As reported in FB25363417: A UIKit based app running on macOS 27.2 (or macOS 27.0.1) via Mac Catalyst no longer has functioning state restoration. Upon app restart, there is no NSUserActivity being provided to the scene in the UISceneDelegate method scene(_:willConnectTo:options:). This can be tested with Apple’s own sample app “Restoring your app’s state”. Just update the sample project with support for a Mac Catalyst build. Using Xcode 27.2 on a Mac with macOS 27.0 or 27.2, build and run the Mac Catalyst version of the app. The main screen appears with a list of products. Select any product so you see details of the product. Quit the app. Run the app again. Note that you are not returned to the previously selected product detail screen. Instead, you just see the main list of products. If you run the same app and perform the same steps on a Mac running macOS 26.x, then when the app is restarted, you correctly get returned to the previously selected product detail screen. The problem is being caused by no NSUserActivity being passed into the scene delegate on app startup. While running the app on a Mac with macOS 27.x, put a breakpoint on the initial guard statement in scene(_:willConnectTo:options:) and you will see there is no activity on app restart. This is impacting paid customers of my existing app since upgrading to macOS 27. They no longer get returned to the app’s previous state when restarting the app. It is expected that state restoration should work on macOS 27 just as well as it does under macOS 26 in an app built with Mac Catalyst.
0
0
126
1w
UITextContentType.cellularIMEI works on iOS 27+ only
During testing, we found that IMEI AutoFill behaves differently by iOS version, independent of the entitlement, and would like to confirm the expected behavior. Test details Implementation: textContentType = .cellularIMEI on the IMEI input field Entitlement status: no carrier-related entitlements in the test build Observed results iOS 27: The IMEI AutoFill suggestion appears and works in any app, regardless of carrier entitlement. iOS 26 and earlier: The IMEI AutoFill suggestion does not appear. Questions Is it the expected and intended behavior that, on iOS 27, IMEI AutoFill is available to any app without a carrier entitlement? On iOS versions earlier than 27 (iOS 17.4 to 26), is the public cellular plan entitlement required for IMEI AutoFill to work? If not, are there other conditions or requirements? On dual-IMEI devices, which IMEI (IMEI or IMEI2) is filled when .cellularIMEI is used on iOS 27? Should we use .cellularIMEI1 / .cellularIMEI2 to specify it explicitly? Thank you for your support.
1
0
160
1w
UIKit snapshot views render empty into UIImage on physical devices, but work in Simulator
Is there a supported way to convert the cached contents of a UIKit snapshot view into a UIImage on physical iOS/iPadOS devices? A view returned by snapshotView(afterScreenUpdates:) displays correctly on hardware, but drawing that view into a UIGraphicsImageRenderer produces no cached-content pixels. drawHierarchy(in:afterScreenUpdates:) still returns true. The same base experiment succeeds in Simulator. Feedback Assistant report: FB25336445. A standalone reproducer and measurements are attached there; use the corrected replica-readback-ios-27.0.1-fixed-project.zip attachment. Tested environments Physical iPhone 15 Pro Max: iOS 27.0.1 (24A446). Physical iPad mini (6th generation): iPadOS 26.6.1 (23G83). Two independent app launches produced identical measurements. Simulator: iPhone 18 Pro / iOS 27.0 and iPhone 15 Pro Max / iOS 26.1. The app is a standalone UIKit Release build, launched without a debugger or XCTest. It uses an ordinary red UIView and a white UILabel: no WebKit, Liquid Glass, video, secure text fields, third-party libraries, or private API calls. I have not tested a physical iPhone on the 26 series or iOS 27.0.2. The Simulator and device OS patch versions differ, so this is not a controlled OS-only comparison. Reproduction Display a red 240 x 160 UIView containing a white UILabel; allow it to render. Draw the original view into an image as a positive control. Call source.snapshotView(afterScreenUpdates: false), attach the replica to the window at the source frame, wait 500 ms, hide the original, then wait another 500 ms. Draw the attached replica into transparent and cyan-prefilled image contexts. Add an ordinary red 30 x 30 child UIView to the replica, wait 500 ms, and capture again. Repeat with replicas from UIWindow.snapshotView and UIScreen.snapshotView. This is the capture operation, called on the main actor after those waits: func rasterize(_ target: UIView, cyanBackground: Bool) -> UIImage { let format = UIGraphicsImageRendererFormat() format.scale = 1 format.opaque = false return UIGraphicsImageRenderer(size: target.bounds.size, format: format) .image { context in if cyanBackground { UIColor.cyan.setFill() context.fill(target.bounds) } let success = target.drawHierarchy( in: target.bounds, afterScreenUpdates: true ) print("drawHierarchy:", success) } }Results On both physical devices: The original 240 x 160 UIView renders normally: all 38,400 pixels are nontransparent. The replica on a transparent target produces zero nontransparent pixels. The replica on a cyan target leaves all 38,400 pixels cyan. Adding an ordinary child view produces approximately 900 red pixels, but the replica's cached contents are still missing. UIView, UIWindow and UIScreen replicas all exhibit the omission, while drawHierarchy returns true. In both tested Simulators, the base experiment renders the replica contents and overwrites the cyan background. The child-marker addition was tested on physical devices only. These counts are measured from the CGImage before PNG encoding. Thus “black output” with an opaque context appears to be missing content, not pixels painted black: transparent and cyan targets retain their original contents. Questions Is bitmap readback of these snapshot views supported on physical devices, or are they only intended for on-screen composition? If unsupported, is the Simulator behavior expected, and why does drawHierarchy return success despite omitting the visible cached contents? Is there a supported API to materialize those cached contents as an image, without starting a screen-recording session? Capturing the original view directly is a useful control, but does not answer how to read back an already-created snapshot. I found this older AVSampleBufferDisplayLayer discussion, which also describes a correctly displayed snapshot view becoming black when converted to an image. My reproducer uses only ordinary UIKit views; I do not know whether the underlying cause is related.
Topic: UI Frameworks SubTopic: UIKit
5
0
366
1w
Best way to position game touch controls around the iPhone Duo hinge
For a full-screen game with a Metal/Unreal rendering view and a SwiftUI overlay for touch controls, what is the recommended way to keep interactive controls away from the hinge while still allowing the rendered game world to use the full display? Would you recommend querying ReservedRegion in the SwiftUI overlay while allowing the underlying render view to remain edge-to-edge? Also, should control placement respond continuously while the device is being folded, or primarily respond to layout/reserved-region changes once the pose changes?
Topic: UI Frameworks SubTopic: SwiftUI
1
0
114
1w
Where can we find the official WWDC session / sample code for adopting the foldable iPhone (this generation's Duo hardware)?
We've been reverse-engineering behavior from the Simulator device profile alone. Is there a WWDC session, updated UIKit/SwiftUI documentation, or sample project specifically covering foldable iPhone adoption (window/scene handling, size-class behavior, collection/table view sizing, and the fold-posture API surface) that we should be building against instead of inferring behavior empirically?
Topic: UI Frameworks SubTopic: UIKit
1
0
143
1w
Is UIScreen.main.bounds valid on iPhone Duo?
During a fold, UIScreen.main.bounds stays at the outer-display size while window.windowScene?.screen.bounds updates. Layout that still reads UIScreen.main (sheet heights, map padding, title widths) is wrong on the inner display. Should apps stop using UIScreen.main entirely and always read the window scene’s screen?
Topic: UI Frameworks SubTopic: UIKit
2
0
343
1w
iPhone Duo supports multiple windows but `requestSceneSessionDestruction` fails due to unsupported device idiom
Problem: iPhone Duo supports multiple windows using Split Views. However, we cannot programmatically close windows using requestSceneSessionDestruction because we get the following error: "This functionality is not supported for this device idiom." This seems like a miss in Apple's requestSceneSessionDestruction implementation. If the Duo is going to let users open multiple windows (where supportsMultipleScenes is true for the Duo), then developers should be able to close them via requestSceneSessionDestruction, too. 🤔 Is this a bug? I have filed a ticket here in case it is: FB25353479 Additional implementation details: Our app supports multiple windows on iPad devices. The Duo is the first phone to support multiple windows as well. For user convenience, our app has an option to combine information from all windows and then collapse everything down to one single window. We use requestSceneSessionDestruction to close the extraneous windows afterward. This works great on iPad, but we get the unsupported device idiom error on the Duo only. We have no way of closing windows programmatically as far as I can tell.
Topic: UI Frameworks SubTopic: UIKit Tags:
2
0
130
1w
macOS 27: reproducible native menu hang in TextEdit using a short mouse sequence
Since upgrading to macOS 27, I have encountered native menus becoming unresponsive. It is reproducible via a short sequence of mouse actions in Apple’s TextEdit application. The following linked zip contains a Python reproduction script and a shell launcher that prepares its dependencies: https://drive.google.com/uc?export=download\&id=1q9DtRC7zpnhK50v4VmvuRAf2sq6I9jaz Expected: The menu continues responding to mouse movement, clicks and Escape. Observed: The menu becomes unresponsive after the sequence. Could anyone confirm whether the attached reproduction triggers the issue on their system? Is this a known AppKit menu-tracking issue, and are there any suggested workarounds or additional diagnostics that would help investigate it? Thank you.
Topic: UI Frameworks SubTopic: AppKit Tags:
1
0
154
1w
iPad: How to prevent the new floating decimalPad when using a keyboard toolbar (iPadOS 26)
On iPad running iOS 26, UIKeyboardType.decimalPad sometimes appears as a floating keypad (compact panel) instead of the docked, full-width keyboard. Our app attaches a custom toolbar via inputAccessoryView, so the floating keypad hides the toolbar and breaks the flow. We’d like to opt out of the floating keypad or force the keyboard to remain docked when a toolbar is present. Environment Device: iPad (multiple models) OS: iPadOS 26.0 App type: UIKit Field: UITextField with keyboardType = .decimalPad We present a custom toolbar via inputAccessoryView Expected Docked (full-width) keyboard so the inputAccessoryView toolbar is visible and sized correctly. Actual A floating decimal keypad appears and covers content; our accessory toolbar isn’t visible/attached to it. Why this matters Our toolbar contains required domain actions (Done/Next, Previous). When the keypad floats, the user loses these controls. Questions Is there a supported way to opt out of the floating numeric keypad on iPad when using decimalPad? Is there an API/trait to prefer docked keyboard (e.g., when an inputAccessoryView is present)?
Topic: UI Frameworks SubTopic: UIKit Tags:
4
0
991
1w
UINavigationBarAppearance background does not extend to the top edge on iPhone Duo
Environment Xcode 27.1 iOS 27.1 iPhone Duo simulator UIKit app built with the iOS 27.1 SDK Issue On iPhone Duo, the background of a system-managed UINavigationBar does not extend completely to the top edge of the window. The navigation bar is configured using UINavigationBarAppearance with an opaque blue background. However, a horizontal white strip remains above the blue navigation bar. I also post a feedback: FB24859353 Questions Is this expected behavior on iPhone Duo? What is the recommended way to style this top region? Should apps add a custom background underlay outside the UINavigationBar bounds? Could this be an iOS 27.1 or iPhone Duo simulator issue? Minimal reproduction code: import UIKit final class DemoTabBarController: UITabBarController { override func viewDidLoad() { super.viewDidLoad() viewControllers = NavigationBarStyle.allCases.map { style in let content = DiagnosticsViewController(style: style) let navigationController = UINavigationController(rootViewController: content) navigationController.tabBarItem = UITabBarItem( title: style.title, image: UIImage(systemName: style.symbolName), selectedImage: nil ) style.apply(to: navigationController.navigationBar) return navigationController } } } enum NavigationBarStyle: CaseIterable { case systemDefault case appearance case legacy var title: String { switch self { case .systemDefault: return "Default" case .appearance: return "Appearance" case .legacy: return "Legacy" } } var symbolName: String { switch self { case .systemDefault: return "iphone" case .appearance: return "paintbrush" case .legacy: return "clock.arrow.circlepath" } } func apply(to navigationBar: UINavigationBar) { switch self { case .systemDefault: break case .appearance: let appearance = UINavigationBarAppearance() appearance.configureWithOpaqueBackground() appearance.backgroundColor = .demoBlue appearance.shadowColor = nil appearance.titleTextAttributes = [.foregroundColor: UIColor.white] navigationBar.tintColor = .white navigationBar.standardAppearance = appearance navigationBar.compactAppearance = appearance navigationBar.scrollEdgeAppearance = appearance case .legacy: navigationBar.tintColor = .white navigationBar.barTintColor = .demoBlue navigationBar.backgroundColor = .demoBlue navigationBar.setBackgroundImage(Self.solidImage(color: .demoBlue), for: .default) navigationBar.shadowImage = UIImage() navigationBar.isTranslucent = false navigationBar.titleTextAttributes = [.foregroundColor: UIColor.white] } } private static func solidImage(color: UIColor) -> UIImage { return UIGraphicsImageRenderer(size: CGSize(width: 1, height: 1)).image { context in color.setFill() context.fill(CGRect(x: 0, y: 0, width: 1, height: 1)) } } } private extension UIColor { static let demoBlue = UIColor(red: 0.0, green: 0.46, blue: 0.70, alpha: 1.0) }
Replies
4
Boosts
2
Views
916
Activity
1w
NSScrollView: Overriding "scrollWheel(with:)" can cause a never-ending live scroll
Overview I'm developing an app that depends on NSScrollView to implement a scrollable and zoomable canvas. I need to override NSScrollView.scrollWheel(with:) to implement Option-zooming (holding Option while scrolling up/down to zoom in/out). I've found that simply adding these three lines of code in my NSScrollView subclass: override func scrollWheel(with event: NSEvent) { super.scrollWheel(with: event) }is enough to cause a live scroll to never end, and NSScrollView.didEndLiveScrollNotification to never fire. My app depends on that notification firing so that it can disable some interactions during a live scroll. Furthermore, while the NSScrollView is "stuck" in the live scroll, it's not possible to perform a live magnify. There are also some other effects, including elevated CPU usage and persistent scroll indicators. The issue is occurring with Xcode 27.1 (27A9275) and macOS 27.2 (26B123). I have modified the macOS App project template to showcase the issue. The sample project, along with a screen recording of the issue, can be downloaded from here: https://drive.google.com/drive/folders/1F5sF2NA230NkGbQdLfbV6vM1XmfY1-uT?usp=sharing I hope that Apple can fix this issue soon, as it's a frustrating user experience when the canvas gets stuck while scrolling. I've already filed this in Feedback Assistant under FB25362729. Steps to Reproduce To recreate the issue, follow these steps: Download and extract the "Xcode Project.zip" file from the link above. Open the extracted "NSScrollViewTest" project in Xcode. Build and run the "NSScrollViewTest" app. Scroll all the way to the right edge of the gray canvas using the horizontal scroll gesture on Magic Trackpad. If you comment out lines 8–10 of ScrollView.swift, the issue goes away. The "Issue Recording.mov" file from the link above provides a detailed video of how to recreate the issue.
Topic: UI Frameworks SubTopic: AppKit
Replies
11
Boosts
0
Views
736
Activity
1w
SplitViewController removed the ability to have a side menu on iPhone
Sometime pre-iOS 26 it was possible to use a SplitViewController so that on iPhone you saw the master as a side menu (e.g. hamburger), and the detail full screen. While on iPad you would see the master displayed in a sidebar that could be closed, with the detail fullscreen. This has changed, using a SplitViewController on iPhone now forces you into having 2 fullscreen screens, with a push/pop layout and a back button. In situations where you want the detail screen to open first, this results in users opening the app to find a back button already presented, despite having not navigated anywhere. They must "return" to a screen they never saw. I really despise this layout and find it to be quite a UX issue. But given the new iPhone Duo, using the SplitViewController is now one of the easiest ways to maintain the necessary responsiveness needed, forcing us to accept this behaviour on regular iPhones. Can we PLEASE get the old functionality back, where we can explicitly state on iPhone that the master will always be displayed as a menu?
Replies
1
Boosts
0
Views
471
Activity
1w
UIKIt, iOS 27, UIDocumentPickerViewController(forExporting: [fileURL])
My App saves files using the UIDocumentPickerViewController. This works from iOS 17 to 26. Usually, you have a file with a given name in your sandbox, which you can then export via the pickerVC. In the pickerVC you change the name. In iOS 27 the file name is greyed-out and you can't change it here. The file can be exported only with the pre-given name. Is this a new behaviour or bug in iOS 27?
Topic: UI Frameworks SubTopic: UIKit
Replies
1
Boosts
0
Views
122
Activity
1w
Age Range Functionality in MacOS 27.2 no handle?
I have a running implementation for an iOS Application which is using AgeRange. It was running very well on Mac OS below 27 and was getting the results. It is still working on iOS 27.2 but now in MacOS 27.2 with the same code base I'm getting an } catch AgeRangeService.Error.notAvailable { NSLog("[AgeRangeDeclaration] Handle not available error")Is there a change for MacOS 27 which has to be implemented or do I have to configure something else?
Topic: UI Frameworks SubTopic: General
Replies
0
Boosts
0
Views
107
Activity
1w
Workaround for NSTableView bugs introduced in macOS 27
MacOS 27 (or perhaps 26, I never used it) introduces two bugs in NSTableView (and delegate). It's always a pleasure when you find that your app no longer works properly. First, when the delegate responds to tableView:pasteboardWriterForRow:, no row can be selected by click & drag (even if the method returns nil). Which mean that clicking and dragging the mouse on rows that are not draggable simply does nothing (no selection), which is a frustrating user experience, especially considering that the same action selects rows on macOS 15. The second bug is that tableView.verticalMotionCanBeginDrag = NO is simply ignored. It doesn’t work. So, a click followed by an immediate vertical drag drags the clicked row instead of selecting rows if tableView:pasteboardWriterForRow: does not return nil. Again, it did select rows on macOS 15. That's what verticalMotionCanBeginDrag = NO is for. To work around the first bug, I implement respondsToSelector: in the delegate to return NO when the selector is tableView:pasteboardWriterForRow: and the clicked row is not draggable. This solution is not elegant, as theclickedRow property of the tableview always returns -1 when the method is called. Which means I need to determine the clicked row by other means (using the mouse location and stuff). (This solution should in principle allow working around the second bug, but I haven’t implemented it yet. It would require determining the delay between the click and the drag and the direction of the drag). So my question is: does anyone see a better workaround for these bugs?
Topic: UI Frameworks SubTopic: AppKit
Replies
3
Boosts
0
Views
272
Activity
1w
NavigationSplitView Binding to NavigationSplitViewColumn reset with every NavigationStack path change
I try to create a Navigation that works on iPhone, iPhone Duo and iPad. NavigationSplitView collapses for compact form factors and makes iPhone Duo support much simpler. The Problem is the semantic of the collapse. Switch from detail to sidebar on compact is not a 'back' action in my case. It should have my choosen Icon and has a meaning. So i wanted to control this using the NavigationSpliViewColumn Binding. This does work forward and backward as long as no NavigationStack was used before. But it stops working when you return to the detail root from a Navigation-Action. I left the Backbutton visible so you can test, that it continues to work, when no Navigation-Action preceeded the switch. Here is my Code: import SwiftUI @Observable final class Compass { var path: [Route] init() { self.path = [] } } enum Route: Hashable { case goal } struct ContentView: View { @Environment(\.horizontalSizeClass) private var hsize @State private var compass: Compass = Compass() @State var column: NavigationSplitViewColumn = .detail var body: some View { NavigationSplitView(preferredCompactColumn: $column) { OverviewScreen(column: $column) } detail: { TodayScreen() .toolbar { ToolbarItem(placement: .topBarLeading) { Button("overview", systemImage: "calendar") { self.column = .sidebar } } } } .environment(compass) .onChange(of: column) { old, new in print("column:", old, "→", new) } } } struct OverviewScreen: View { @Binding var column: NavigationSplitViewColumn @Environment(Compass.self) var compass var body: some View { @Bindable var compass = self.compass ScrollView { Text("Overview") .font(.largeTitle) .fontWeight(.heavy) Button("Switch") { self.column = .detail } } } } struct TodayScreen: View { @Environment(Compass.self) var compass var body: some View { @Bindable var compass = self.compass NavigationStack(path: $compass.path) { ScrollView { Text("Today") .font(.largeTitle) .fontWeight(.heavy) Button("Goals programtically", systemImage: "flag.fill") { self.compass.path = [.goal] } NavigationLink(value: Route.goal) { Label("Goal Link", systemImage: "flag.fill") } } .navigationDestination(for: Route.self, destination: self.screen) } } @ContentBuilder func screen(for route: Route) -> some View { switch route { case .goal: Text("Goals") } } } #Preview { ContentView() }This seems unexpected behaviour. If you ask AI the mental model is NavigationSplitViewColumn represents which column is currently visible for the user. That model would be wrong. Also i can't understand why a NavigationStack has to change the Binding? What am i missing here? Is my idea of the programmatic switch not supported? There are other ways to push from compact to your detail column again, but they all have trade-offs or run into other problems. I would appreciate any help here. AI has not understood this and only does surface level work arounds that fix nothing.
Replies
0
Boosts
0
Views
60
Activity
1w
NSSegmentedControl style ineffective.
I'm not sure if it's something wrong with my XCode install (Version 27.1, macOS 27.2) or what, because such a serious issue should be mentioned already... Basically, building my objC app with the latest XCode makes the NSSegmentedControl style ineffective. Likewise, changing the style in the attribute of the control in interface builder has no visible effect on the preview either. Changing the style in code or in IB has no effect. The control appears stuck with a style that implements a blue background for the selected segment (some default style I guess). I tried with a minimalistic app that includes only one window and the control. The issue is still present. Any suggestion? Am I the only one experiencing this?
Topic: UI Frameworks SubTopic: AppKit
Replies
8
Boosts
0
Views
513
Activity
1w
NSScrollView scrolling hitch
When scrolling a basic NSScrollView there seems to be a sudden jump after each flick. Scrolling does not appear smooth and is disorientating. A scroll jump seems to happen directly after letting go of a scroll flick using a trackpad/mouse. Right at that moment the scroll turns into a momentum scroll, slowly decreasing the speed. But the first frame after the gesture the content jumps forward, more than what is expected. Observations: Counterintuitively, scrolling appears to be smoother when disabling NSScrollView.isCompatibleWithResponsiveScrolling. If disabled using a custom NSScrollView subclass there is no large jump anymore. Scrolling also appears to be smoother using a SwiftUI ScrollView. I assume that has the same behaviour as a disabled isCompatibleWithResponsiveScrolling Ironically a WKWebView scrolls much smoother. No sudden jump is observable. It also seems to scroll with faster acceleration, but the individual frames do appear smoother. Why is this better than a native NSScrollView? Elastic scrolling at the bounds of the scroll view also appears much smoother for WKWebViews. When pulling to refresh there is a jump for NSScrollView/SwiftUI, but not for WKWebView. When using an NSScrollView with isCompatibleWithResponsiveScrolling disabled, scrolling appears just as smooth as WKWebView on macOS 13 Ventura and below. On macOS 14 Sonoma scrolling behaviour is suddenly different. Please see a sample project with 4 different scroll views side by side: https://github.com/floorish/ScrollTest Screen recordings show the sudden jumps when scrolling and when elastic scrolling. Tested on Intel & Arm Macs, macOS 11 Big Sur through 15 Sequoia, built with Xcode 16. Should isCompatibleWithResponsiveScrolling be disabled on Sonoma+? Are there any drawbacks? There is also no overdraw anymore since Monterey, as described in https://developer.apple.com/library/archive/releasenotes/AppKit/RN-AppKitOlderNotes/#10_9Scrolling Even with responsive scrolling disabled, why is WKWebView scrolling much smoother than NSScrollView?
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
9
Boosts
3
Views
1.4k
Activity
1w
What pattern to use for an iPhone Tabview app
I have an iPhone tab view application that has not been designed for iPad, and I am aiming to add a left-hand bar that summarises some content and keeps visible what is normally a sheet. What pattern would work best for this? At present, I pass the view to another view with a navigation stack containing an arrangement view with the previous view and then the sidebar as a secondary view within it—would that be the appropriate approach?
Topic: UI Frameworks SubTopic: SwiftUI
Replies
3
Boosts
0
Views
434
Activity
1w
State Restoration no longer works in a Mac Catalyst based app when run on macOS 27.x
As reported in FB25363417: A UIKit based app running on macOS 27.2 (or macOS 27.0.1) via Mac Catalyst no longer has functioning state restoration. Upon app restart, there is no NSUserActivity being provided to the scene in the UISceneDelegate method scene(_:willConnectTo:options:). This can be tested with Apple’s own sample app “Restoring your app’s state”. Just update the sample project with support for a Mac Catalyst build. Using Xcode 27.2 on a Mac with macOS 27.0 or 27.2, build and run the Mac Catalyst version of the app. The main screen appears with a list of products. Select any product so you see details of the product. Quit the app. Run the app again. Note that you are not returned to the previously selected product detail screen. Instead, you just see the main list of products. If you run the same app and perform the same steps on a Mac running macOS 26.x, then when the app is restarted, you correctly get returned to the previously selected product detail screen. The problem is being caused by no NSUserActivity being passed into the scene delegate on app startup. While running the app on a Mac with macOS 27.x, put a breakpoint on the initial guard statement in scene(_:willConnectTo:options:) and you will see there is no activity on app restart. This is impacting paid customers of my existing app since upgrading to macOS 27. They no longer get returned to the app’s previous state when restarting the app. It is expected that state restoration should work on macOS 27 just as well as it does under macOS 26 in an app built with Mac Catalyst.
Replies
0
Boosts
0
Views
126
Activity
1w
UITextContentType.cellularIMEI works on iOS 27+ only
During testing, we found that IMEI AutoFill behaves differently by iOS version, independent of the entitlement, and would like to confirm the expected behavior. Test details Implementation: textContentType = .cellularIMEI on the IMEI input field Entitlement status: no carrier-related entitlements in the test build Observed results iOS 27: The IMEI AutoFill suggestion appears and works in any app, regardless of carrier entitlement. iOS 26 and earlier: The IMEI AutoFill suggestion does not appear. Questions Is it the expected and intended behavior that, on iOS 27, IMEI AutoFill is available to any app without a carrier entitlement? On iOS versions earlier than 27 (iOS 17.4 to 26), is the public cellular plan entitlement required for IMEI AutoFill to work? If not, are there other conditions or requirements? On dual-IMEI devices, which IMEI (IMEI or IMEI2) is filled when .cellularIMEI is used on iOS 27? Should we use .cellularIMEI1 / .cellularIMEI2 to specify it explicitly? Thank you for your support.
Replies
1
Boosts
0
Views
160
Activity
1w
UIKit snapshot views render empty into UIImage on physical devices, but work in Simulator
Is there a supported way to convert the cached contents of a UIKit snapshot view into a UIImage on physical iOS/iPadOS devices? A view returned by snapshotView(afterScreenUpdates:) displays correctly on hardware, but drawing that view into a UIGraphicsImageRenderer produces no cached-content pixels. drawHierarchy(in:afterScreenUpdates:) still returns true. The same base experiment succeeds in Simulator. Feedback Assistant report: FB25336445. A standalone reproducer and measurements are attached there; use the corrected replica-readback-ios-27.0.1-fixed-project.zip attachment. Tested environments Physical iPhone 15 Pro Max: iOS 27.0.1 (24A446). Physical iPad mini (6th generation): iPadOS 26.6.1 (23G83). Two independent app launches produced identical measurements. Simulator: iPhone 18 Pro / iOS 27.0 and iPhone 15 Pro Max / iOS 26.1. The app is a standalone UIKit Release build, launched without a debugger or XCTest. It uses an ordinary red UIView and a white UILabel: no WebKit, Liquid Glass, video, secure text fields, third-party libraries, or private API calls. I have not tested a physical iPhone on the 26 series or iOS 27.0.2. The Simulator and device OS patch versions differ, so this is not a controlled OS-only comparison. Reproduction Display a red 240 x 160 UIView containing a white UILabel; allow it to render. Draw the original view into an image as a positive control. Call source.snapshotView(afterScreenUpdates: false), attach the replica to the window at the source frame, wait 500 ms, hide the original, then wait another 500 ms. Draw the attached replica into transparent and cyan-prefilled image contexts. Add an ordinary red 30 x 30 child UIView to the replica, wait 500 ms, and capture again. Repeat with replicas from UIWindow.snapshotView and UIScreen.snapshotView. This is the capture operation, called on the main actor after those waits: func rasterize(_ target: UIView, cyanBackground: Bool) -> UIImage { let format = UIGraphicsImageRendererFormat() format.scale = 1 format.opaque = false return UIGraphicsImageRenderer(size: target.bounds.size, format: format) .image { context in if cyanBackground { UIColor.cyan.setFill() context.fill(target.bounds) } let success = target.drawHierarchy( in: target.bounds, afterScreenUpdates: true ) print("drawHierarchy:", success) } }Results On both physical devices: The original 240 x 160 UIView renders normally: all 38,400 pixels are nontransparent. The replica on a transparent target produces zero nontransparent pixels. The replica on a cyan target leaves all 38,400 pixels cyan. Adding an ordinary child view produces approximately 900 red pixels, but the replica's cached contents are still missing. UIView, UIWindow and UIScreen replicas all exhibit the omission, while drawHierarchy returns true. In both tested Simulators, the base experiment renders the replica contents and overwrites the cyan background. The child-marker addition was tested on physical devices only. These counts are measured from the CGImage before PNG encoding. Thus “black output” with an opaque context appears to be missing content, not pixels painted black: transparent and cyan targets retain their original contents. Questions Is bitmap readback of these snapshot views supported on physical devices, or are they only intended for on-screen composition? If unsupported, is the Simulator behavior expected, and why does drawHierarchy return success despite omitting the visible cached contents? Is there a supported API to materialize those cached contents as an image, without starting a screen-recording session? Capturing the original view directly is a useful control, but does not answer how to read back an already-created snapshot. I found this older AVSampleBufferDisplayLayer discussion, which also describes a correctly displayed snapshot view becoming black when converted to an image. My reproducer uses only ordinary UIKit views; I do not know whether the underlying cause is related.
Topic: UI Frameworks SubTopic: UIKit
Replies
5
Boosts
0
Views
366
Activity
1w
Best way to position game touch controls around the iPhone Duo hinge
For a full-screen game with a Metal/Unreal rendering view and a SwiftUI overlay for touch controls, what is the recommended way to keep interactive controls away from the hinge while still allowing the rendered game world to use the full display? Would you recommend querying ReservedRegion in the SwiftUI overlay while allowing the underlying render view to remain edge-to-edge? Also, should control placement respond continuously while the device is being folded, or primarily respond to layout/reserved-region changes once the pose changes?
Topic: UI Frameworks SubTopic: SwiftUI
Replies
1
Boosts
0
Views
114
Activity
1w
Where can we find the official WWDC session / sample code for adopting the foldable iPhone (this generation's Duo hardware)?
We've been reverse-engineering behavior from the Simulator device profile alone. Is there a WWDC session, updated UIKit/SwiftUI documentation, or sample project specifically covering foldable iPhone adoption (window/scene handling, size-class behavior, collection/table view sizing, and the fold-posture API surface) that we should be building against instead of inferring behavior empirically?
Topic: UI Frameworks SubTopic: UIKit
Replies
1
Boosts
0
Views
143
Activity
1w
Is UIScreen.main.bounds valid on iPhone Duo?
During a fold, UIScreen.main.bounds stays at the outer-display size while window.windowScene?.screen.bounds updates. Layout that still reads UIScreen.main (sheet heights, map padding, title widths) is wrong on the inner display. Should apps stop using UIScreen.main entirely and always read the window scene’s screen?
Topic: UI Frameworks SubTopic: UIKit
Replies
2
Boosts
0
Views
343
Activity
1w
iPhone Duo supports multiple windows but `requestSceneSessionDestruction` fails due to unsupported device idiom
Problem: iPhone Duo supports multiple windows using Split Views. However, we cannot programmatically close windows using requestSceneSessionDestruction because we get the following error: "This functionality is not supported for this device idiom." This seems like a miss in Apple's requestSceneSessionDestruction implementation. If the Duo is going to let users open multiple windows (where supportsMultipleScenes is true for the Duo), then developers should be able to close them via requestSceneSessionDestruction, too. 🤔 Is this a bug? I have filed a ticket here in case it is: FB25353479 Additional implementation details: Our app supports multiple windows on iPad devices. The Duo is the first phone to support multiple windows as well. For user convenience, our app has an option to combine information from all windows and then collapse everything down to one single window. We use requestSceneSessionDestruction to close the extraneous windows afterward. This works great on iPad, but we get the unsupported device idiom error on the Duo only. We have no way of closing windows programmatically as far as I can tell.
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
2
Boosts
0
Views
130
Activity
1w
macOS 27: reproducible native menu hang in TextEdit using a short mouse sequence
Since upgrading to macOS 27, I have encountered native menus becoming unresponsive. It is reproducible via a short sequence of mouse actions in Apple’s TextEdit application. The following linked zip contains a Python reproduction script and a shell launcher that prepares its dependencies: https://drive.google.com/uc?export=download\&id=1q9DtRC7zpnhK50v4VmvuRAf2sq6I9jaz Expected: The menu continues responding to mouse movement, clicks and Escape. Observed: The menu becomes unresponsive after the sequence. Could anyone confirm whether the attached reproduction triggers the issue on their system? Is this a known AppKit menu-tracking issue, and are there any suggested workarounds or additional diagnostics that would help investigate it? Thank you.
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
1
Boosts
0
Views
154
Activity
1w
iPad: How to prevent the new floating decimalPad when using a keyboard toolbar (iPadOS 26)
On iPad running iOS 26, UIKeyboardType.decimalPad sometimes appears as a floating keypad (compact panel) instead of the docked, full-width keyboard. Our app attaches a custom toolbar via inputAccessoryView, so the floating keypad hides the toolbar and breaks the flow. We’d like to opt out of the floating keypad or force the keyboard to remain docked when a toolbar is present. Environment Device: iPad (multiple models) OS: iPadOS 26.0 App type: UIKit Field: UITextField with keyboardType = .decimalPad We present a custom toolbar via inputAccessoryView Expected Docked (full-width) keyboard so the inputAccessoryView toolbar is visible and sized correctly. Actual A floating decimal keypad appears and covers content; our accessory toolbar isn’t visible/attached to it. Why this matters Our toolbar contains required domain actions (Done/Next, Previous). When the keypad floats, the user loses these controls. Questions Is there a supported way to opt out of the floating numeric keypad on iPad when using decimalPad? Is there an API/trait to prefer docked keyboard (e.g., when an inputAccessoryView is present)?
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
4
Boosts
0
Views
991
Activity
1w