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

A Summary of the iPhone Duo Group Lab
Group Labs are a unique opportunity for the community to submit questions directly to a panel of Apple engineers and designers. Here are the highlights from the iPhone Duo Group Labs: How should apps preserve navigation and UI state when switching between the inner and outer displays? Treat display transitions as size-class and trait changes, not a scene disconnect or app termination; your process stays alive. For more information, see Prepare your app for iPhone Duo. For state that must survive a scene disconnect/reconnect, implement stateRestorationActivity(for:) to save an NSUserActivity Restoring your app's state. Do multiple instances of the same app on iPhone Duo share UserDefaults/@AppStorage state? Multiple instances of your app's UI on iPhone Duo behave similarly to multi-window support on iPadOS. To learn more, see Leverage multiple displays and scenes on iPhone Duo. Both UserDefaults and AppStorage are app-wide, not per-window, stores. If a full-screen app on the inner display is closed, does it move to the outer display or get backgrounded? iPhone Duo honors UIRequiresFullScreen and apps adapt in place as the device opens and closes rather than backgrounding. To learn more, watch Prepare your app for iPhone Duo. How should apps preserve state — text input, scroll position, video playback, camera sessions — during hinge angle transitions? For example, when a LazyVGrid's column count changes because the device folds, does SwiftUI preserve scroll position automatically, or should you use scrollPosition(id:)? The system generally preserves text input and scroll position automatically since hinge angle changes are represented as size-class and trait updates, not a scene disconnect or app termination. This applies even to cases like a LazyVGrid column-count change triggered by opening or closing the device — apps typically don't need to manually manage scroll position with scrollPosition(id:anchor:) for this transition. For more info, see Prepare your app for iPhone Duo. How can apps preserve what someone is doing when switching displays or folding/unfolding? Treat this as a resize/trait-change event, not app teardown — your process keeps running as size classes change. See Prepare your app for iPhone Duo to learn more. For scenes that actually disconnect and reconnect, implement stateRestorationActivity(for:) to save an NSUserActivity Restoring your app's state. How does actively playing video behave through the hinge angle animation? The system generally preserves video playback and player position automatically since hinge angle changes are represented as size-class and trait updates, not a scene disconnect or app termination. AVKit will scale and resize the video automatically. If a user folds or unfolds the device mid-checkout, what does the system preserve automatically, and what should the app manage itself to avoid lost input or duplicate requests? When someone opens or closes an iPhone Duo, the system represents this as a size-class and trait collection change, not a scene disconnect or app teardown, so in-memory state like input fields typically persists automatically since the app’s process keeps running. For more info, see Prepare your app for iPhone Duo. How should apps handle the keyboard and text input when the device folds or unfolds while typing? As iPhone Duo folds or unfolds, the available screen geometry and framing change. Ensure your app adopts standard layout controls, containers, and size classes to handle resizability gracefully across all poses. When a text field becomes first responder, the system automatically shows the keyboard and binds its input to the text field. Because the appearance of the keyboard has the potential to obscure portions of your user interface, you should update your interface as needed to ensure that the text field being edited remains visible. Use keyboard notifications such as keyboardWillShowNotification, keyboardWillHideNotification, and keyboardWillChangeFrameNotification to detect the appearance and disappearance of the keyboard and to make necessary changes to your interface layout. To learn more, see UITextField. If someone is typing and closes iPhone Duo, does the keyboard/editing session survive the hinge transition, or does it get a new scene? When a user types and closes iPhone Duo, the active editing session and keyboard do not get a completely new scene. Instead, the app undergoes a dynamic resizing and transitions from the inner display to the compact outer display, maintaining the existing scene and application state. For more info, watch Prepare your app for iPhone Duo.
16
0
899
2d
Supported way to put an iPhone Duo simulator into the unfolded state programmatically
The Duo simulator boots showing only the outer display: the window is fixed at 382×644 pt and our layout classifier always reports the compact stack mode. We measured this on two separate clean boots (shutdown, erase, boot). xcrun simctl help lists no subcommand for folding, posture, or selecting the inner display — we read the full list. xcrun simctl io screenshot does reveal a second display (LCD-1, 2007×2853 px, aspect 0.70, close to the 669×951 inner portrait size). Unfolding manually in the Simulator UI works and the app then renders the two-column layout correctly, but we could not find a programmatic equivalent. Is there a supported way to unfold a Duo simulator from the command line or from XCTest?
Topic: UI Frameworks SubTopic: SwiftUI
3
3
688
14h
sidebarAdaptable Design Problem
This is what Apple's Destination Video Sample App looks like on iPhone Duo built with SDK 27.1 beta. Two things: Items that should not appear in the tab bar appear. There is no sidebar for iPhone Duo. So my problem is: is this a bug or a design on purpose? Will sidebarAdaptable gets a sidebar on iPhone Duo? Or at least, how to hide these things that should only appear in the sidebar? The sample app uses .defaultVisibility(, for:) and .hidden() but obviously none of these takes effect.
Topic: UI Frameworks SubTopic: SwiftUI
0
0
147
18h
Enable iPhone Duo Upside Down Orientation
Ever since the iPhone X, upside-down orientation on the iPhone has been disabled by design. I haven't found any official documentation explaining why, but my guess is it has to do with Face ID and the top notch. However, now that the iPhone Duo has no Face ID or notch—and includes reserved occlusion regions—why not enable upside-down rotation? As of iOS 27.1, it remains disabled. Leaving it turned off only confuses users, making them think their favorite apps are frozen when they won't rotate.
Topic: UI Frameworks SubTopic: SwiftUI
1
1
305
20h
iPhone Duo and the Safe-Area
I took a screenshot of the Safety Area's and Occlusions on the iPhone Duo outer display. The article Designing for iPhone Duo tells us to... Consider using the full display width for interfaces where bars aren’t necessary. Some layouts can span the full display, which works well for visual, immersive interfaces that don’t scroll, as long as nothing conflicts with the Dynamic Island or the status bar. Calculator, for example, occupies the full width of the display. You can also combine both approaches, letting a background image or header span the full width while scrollable content stays inset. The Graphics Content can easily take up the full space which can be achieved by ignoring the safe area (.ignoresSafeArea()). And knowing the iPhone Duo there is no occlusion so I can also ignore the safe area for the interactable content. However we now are entering an awkward state. Because now I need to make decisions based on a specific device. Knowing the iPhone Duo I can ignore horizontal safe area and expand to full width because there is no occlusions here, but ignoring the safe-area may result in unexpected behavior on other (future) devices which then requires me to use code that specificly targets certain devices. I wished SwiftUI had something that I could safely expand the interactable content the full width.
Topic: UI Frameworks SubTopic: SwiftUI
2
0
101
20h
iOS 27: UIApplication.shared.open fail for relative URL values that resolve to valid https URLs
A URL created with URL(string:relativeTo:) that used to work in iOS26 and below with UIApplication.shared.open stopped working in iOS27, the app has not been built yet with iOS27 SDK. Have anyone seen this issue, all the links work perfectly in iOS26 and below. We found a solution to use .absoluteURL but still want to check with the community, I havent seen any mention of this this that it will break try the below sample code import UIKit struct RelativeURLReproView: View { @State private var log = "Tap a button. Watch this log and whether Safari actually appears.\n" var body: some View { VStack(alignment: .leading, spacing: 16) { Button("Open relative URL") { openTarget(.relative) } .buttonStyle(.borderedProminent) Button("Open absoluteURL") { openTarget(.absolute) } .buttonStyle(.bordered) Button("Clear log") { log = "" } ScrollView { Text(log) .font(.system(.footnote, design: .monospaced)) .textSelection(.enabled) .frame(maxWidth: .infinity, alignment: .leading) } } .padding() } private enum ReproTarget { case relative case absolute } private func append(_ line: String) { log.append(line + "\n") print(line) } private func openTarget(_ target: ReproTarget) { log = "" let base = URL(string: "https://www.example.com")! let relative = URL(string: "about/help", relativeTo: base)! let url = (target == .relative) ? relative : relative.absoluteURL append("target: \(target == .relative ? "relative" : "absoluteURL")") append("url: \(url)") append("absoluteString: \(url.absoluteString)") append("scheme: \(url.scheme ?? "nil")") append("baseURL: \(url.baseURL?.absoluteString ?? "nil")") append("relativeString: \(url.relativeString)") append("canOpenURL: \(UIApplication.shared.canOpenURL(url))") append("Calling UIApplication.shared.open…") append("Did Safari actually appear? Check by eye.") UIApplication.shared.open(url, options: [:]) { success in Task { @MainActor in append("open completion: \(success)") } } } } #Preview { RelativeURLReproView() }
4
0
59
23h
viewDidDisappear is not called on a popped view controller when switching tabs during UITabBarController's reselect pop-to-root on iOS 27
Issue Description Hi, I would like to share an issue with UIViewController's appearance callbacks inside UITabBarController + UINavigationController on iOS 27. When a tab containing a UINavigationController with two view controllers is re-tapped, UIKit starts its built-in animated pop-to-root. On iOS 27, if the user switches to another tab while that pop animation is still in flight, the popped view controller receives viewWillDisappear: (with isMovingFromParent == true), but viewDidDisappear: is never called on it. The appearance callbacks stay unbalanced. This breaks code that relies on viewDidDisappear: + isMovingFromParent to detect that a view controller was popped. Steps to Reproduce Create a UITabBarController with two tabs. The first tab is a UINavigationController. In the first tab, push a second view controller ("Nested"). Tap the first tab item again. UIKit starts the animated pop-to-root. Immediately (while the pop animation is still running), tap the second tab item. Expected vs. Actual Behavior Expected: On iOS 26, "Nested" receives viewWillDisappear: and then viewDidDisappear:, both with isMovingFromParent == true. Actual: On iOS 27, "Nested" receives only viewWillDisappear:. viewDidDisappear: is NOT called, even though "Nested" is no longer in navigationController.viewControllers. Note: On iOS 27, if the second tab is tapped after the pop animation has finished, viewDidDisappear: is delivered correctly. The issue only occurs when the tab switch happens during the pop transition. Environment Xcode Version 27.0 iOS 27.0 iPhone 18 Pro simulator: reproduces iOS 26.0 iPhone 17 Pro simulator: does not reproduce Feedback Assistant Report ID: FB24934469 Minimal Reproduction Example // SceneDelegate.swift import UIKit class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = scene as? UIWindowScene else { return } let window = UIWindow(windowScene: windowScene) window.rootViewController = TabBarController() window.makeKeyAndVisible() self.window = window } } // TabBarController.swift import UIKit final class TabBarController: UITabBarController { override func viewDidLoad() { super.viewDidLoad() let firstNav = UINavigationController(rootViewController: HomeViewController()) firstNav.tabBarItem = UITabBarItem(title: "First", image: UIImage(systemName: "house"), tag: 0) let second = LoggingViewController(name: "Second") second.tabBarItem = UITabBarItem(title: "Second", image: UIImage(systemName: "star"), tag: 1) viewControllers = [firstNav, second] } } class LoggingViewController: UIViewController { let name: String init(name: String) { self.name = name super.init(nibName: nil, bundle: nil) title = name } required init?(coder: NSCoder) { fatalError() } override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .systemBackground } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) print("[\(name)] viewWillDisappear isMovingFromParent=\(isMovingFromParent)") } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) print("[\(name)] viewDidDisappear isMovingFromParent=\(isMovingFromParent)") } } final class HomeViewController: LoggingViewController { init() { super.init(name: "Home") } required init?(coder: NSCoder) { fatalError() } override func viewDidLoad() { super.viewDidLoad() navigationItem.rightBarButtonItem = UIBarButtonItem( title: "Push", primaryAction: UIAction { [weak self] _ in self?.navigationController?.pushViewController(LoggingViewController(name: "Nested"), animated: true) } ) } }
Topic: UI Frameworks SubTopic: UIKit
0
0
33
23h
Repeated Swift error breakpoint stops in system frameworks during AppKit startup and window creation
I debug an Objective-C++ AppKit application in CLion. The application runs normally, but a “When any is thrown” breakpoint stops repeatedly during startup and window creation, making it difficult to debug. One stop occurs before any window is created: [NSApplication run] → finishLaunching → _customizeMainMenu → [NSTextView _supportsWritingTools] → GenerativeModels → JSONDecoder → swift_willThrow. LLDB identifies a decoding frame as GenerativeModels.AvailabilityStore.ReadinessEntry.Criteria.init(from:). Other stops occur while NSDocumentController attempts to reopen documents, and while AppKit resets gesture recognizers during NSWindow creation. All the supplied stops reach swift_willThrow; the app continues after resuming. Are these expected handled errors? Is there a supported way to prevent the startup Writing Tools check from throwing? I can provide the complete stacks and a minimal reproduction if helpful. I'm on MacOS Tahoe 26.6.2 (25G83) Xcode 26.4.1 - Build version 17E202 Apple clang version 21.0.0 (clang-2100.0.123.102) I'm building from within CLion 2026.2.3 and using the bundled LLDB (21.1.7), but the problem also occurs when using the one from XCode (21.0) Disabling Apple Intelligence in the OS settings does not help.
Topic: UI Frameworks SubTopic: AppKit
0
0
26
1d
CALayer with valid contents and correct configuration is excluded from window compositing on Apple Silicon (works fine on Intel)
macOS/Hardware details: macOS version: 27.0 (build 26A428) Hardware: Apple Silicon Mac (arm64) App architecture: Native arm64 Xcode/SDK: Built against MacOSX27.0 SDK Deployment target: MACOSX_DEPLOYMENT_TARGET = 26.0 Regression history: Same app/codebase previously built and ran correctly on macOS 13 (Ventura), Intel — issue only appears after migrating the build to Apple Silicon; no changes were made to the affected view's drawing or layer-configuration code between the two builds We have a custom, layer-backed NSView (part of a hand-rolled tree/list control that draws its own content via Core Graphics into the layer's contents) that renders completely blank on screen on Apple Silicon Macs, while an adjacent sibling view using the identical view class, drawing code, and layer configuration renders correctly. Using lldb and Xcode's View Debugger against the live process, we've confirmed: The layer's actual backing content is correct: capturing it directly via -renderInContext: produces the expected fully-drawn image (text and icons all present). Every inspectable property of the broken view/layer (hidden, alphaValue, opaque, wantsLayer, isFlipped/isGeometryFlipped, zPosition, masksToBounds, contentsScale, mask, transform, backgroundColor, contents, sublayers, superlayer) is identical to the working sibling view — no configuration difference exists anywhere. The layer's superlayer link is intact and points to the correct parent, ruling out a detached/orphaned layer. Standard remediation attempts — setNeedsDisplay:, displayIfNeeded, toggling wantsLayer, detaching/reattaching the view from its superview, changing zPosition — all have zero effect. Most notably, directly setting layer.backgroundColor to an opaque solid color on the live, correctly-connected layer (verified via property readback) produces no visible change on screen at all. Because even an unconditional background color change is not reflected, the layer appears to be excluded from what's actually sent to the window server for compositing, rather than simply failing to draw updated content. Since all inspectable state is correct and identical to a working sibling view, we've been unable to identify any application-level cause. The view remains fully interactive — clicks and hit-testing resolve correctly to the right underlying data — only the visual output is missing. Are there known Apple Silicon-specific changes to CALayer/NSView compositing (window server layer inclusion, contentsScale/backing-store allocation, or layer-backed view promotion) that could cause a fully valid, connected CALayer with correct contents to be silently dropped from the composited frame? Any suggestions for further diagnostic tools (e.g. Quartz Debug, CARenderServer logging, or WindowServer compositing traces) to narrow this down further would help.
Topic: UI Frameworks SubTopic: AppKit
0
0
11
1d
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?
0
0
46
1d
Charts are broken with Xcode 27, Plotting multiple lines
Hi, Charts—specifically those with multiple lines—are broken in Xcode 27. First, I spotted the bug in my program, and then I checked your example. Your own example Plotting-multiple-lines is not working correctly anymore. It shows 1 line or sometimes no lines at all, depending on the order of the data. It depends on how the data is passed to the chart. If the data is passed as separate series, it works. In Visualizing your app’s data it works, but the data is passed as described before. Don't follow Microslop: have the AI ​​generate the code and then skip the tests. This is a serious bug that requires a lot of work to rearrange the data, just to work around the issue. Christian
0
0
218
1d
App Intents and the Document App Xcode Template
I’m working on an app that deals with a list of text items, so I started with the document app template in Xcode. I have the app basically doing what I want it to do, but I want to be a good ecosystem citizen, so I’d like to conform to app intents. I think that app intents will able to do what I want - accepting text and passing it back out - but I can’t figure out how to access the document outside of my content view and associated subviews. Any guidance would be appreciated. Thank you, Don Carlile
1
0
400
1d
macOS 26.7: a side Dock prevents quarter tiling at the adjacent upper corner
I found that the failing corner in native macOS window tiling changes with the Dock position. With the Dock on the right, the upper-right corner produces the right half instead of a quarter. With the Dock on the left, the upper-left corner produces the left half instead of a quarter. With the Dock at the bottom, all four corners produce quarters. Apple's macOS Tahoe guide describes dragging to any corner as a way to tile a window there. Configuration Mac mini Mac14,12, Apple M2 Pro macOS Tahoe 26.7 (25G229) One external iiyama PL4071UH (ProLite X4071UHSU) display, with a [native panel resolution of 3840 × 2160]; no adjacent display and mirroring off. A 3840 × 2160 mode is available in macOS, but it was not the mode used for these measurements. Active macOS display mode reported by CGDisplayMode and System Information: 3008 × 1692 pixels at 60 Hz; the interface “looks like” 1504 × 846 points (2× backing scale). This is a scaled configuration on the 4K display. NSScreen.frame: 1504 × 846 points. NSScreen.visibleFrame with the Dock on the right: approximately 1456 × 816 points (about 48 points removed at the right for the Dock and 30 at the top for the menu bar). macOS reports Television: Yes for this display and exposes an Underscan control in Displays settings. The slider appeared at the “No” end during inspection; its effect on this tiling behavior has not been tested. Dock position changed between right, left, and bottom for the comparison below Dock auto-hide is currently off (com.apple.dock autohide = 0) Native drag-to-edge tiling and the Option-key tiling accelerator enabled; tiled window margins disabled Upper-right Hot Corner configured without a modifier key during the right-Dock measurement Steps to reproduce Open a blank, resizable TextEdit window and enable native drag-to-edge tiling. Set the Dock position to Right in System Settings → Desktop & Dock. Drag the window by its title bar to each screen corner and release after the tiling preview appears. Set the Dock position to Left and repeat. Set the Dock position to Bottom and repeat. Dock-position comparison Dock position Upper-left corner Upper-right corner Lower corners Right quarter right half quarters Left left half quarter quarters Bottom quarter quarter quarters The left- and bottom-Dock comparisons are direct user observations. The right-Dock case was also measured programmatically as described below. This pattern points to a side-Dock interaction with detection of the adjacent upper corner; the internal cause is not yet established. The display's scaled mode and its classification as a television are additional variables worth recording. Neither has been isolated as a cause: the controlled change so far is the Dock position. A useful follow-up would be to repeat the same corner tests at another display mode, including 3840 × 2160, with the Dock kept on the same side, and to record the Underscan setting. Instrumented result with Dock on the right I sampled NSEvent.mouseLocation every 20 ms, used CGEventSource.buttonState to identify the release, and read the window bounds using CGWindowListCopyWindowInfo about 0.6 seconds later. The same TextEdit window ID was observed for all four corner tests. Pointer and window coordinates below use the top-left of the display as (0, 0); dimensions are in macOS points. Release corner Pointer (x, y) Window (x, y, width, height) Result Top left (0, 0) (-1, 30, 727, 409) quarter Top right (1503.98, 0) (727, 30, 728, 816) RIGHT HALF Bottom left (0, 845.98) (-1, 438, 727, 409) quarter Bottom right (1503.98, 845.98) (727, 438, 728, 409) quarter At the upper-right release, the pointer is effectively at the screen's rightmost x coordinate and at y = 0. The resulting window is 816 points high, compared with 409 points for each quarter tile. The Hot Corner did not prevent the pointer from reaching that coordinate. Expected result Dragging to any of the four corners should produce the corresponding quarter regardless of whether the Dock is on the right, left, or bottom.
Topic: UI Frameworks SubTopic: General Tags:
0
0
52
1d
How to implement correct horizontal padding for iPhone Duo
The iPhone Duo outer screen displays a vertical bar on the right edge with view contents inset. A SwiftUI Form displays an appropriate amount of leading padding but 0 padding on the trailing edge, since the vertical bar provides some visual margins already that looks nice. I have a view that looks kind of like a form, multiple stacked text fields, that should align the same way. I used scenePadding to achieve which looks correct on iPhone 18 Pro perfectly aligned with Form, but on iPhone Duo there is extra trailing padding. It doesn't align with my Edit button that remains in the horizontal axis navigation bar (and it is not inset enough on the leading edge, off by a few pixels, interestingly). Note when you unfold it and add the app on the left side in Split View, the vertical bar is on the leading edge, in which case there's too much padding on the leading edge. How can I achieve the correct layout padding/margins? iPhone 18 Pro vs iPhone Duo: My actual app: struct ContentView: View { var body: some View { TabView { NavigationStack { SystemFormView() .navigationTitle("System Form") } .tabItem { Label("System Form", systemImage: "list.bullet.rectangle") } NavigationStack { CustomFormView() .navigationTitle("Custom Form") } .tabItem { Label("Custom Form", systemImage: "rectangle.3.group") } } } } private struct SystemFormView: View { var body: some View { Form { Text("Row 1") Text("Row 2") Text("Row 3") } } } private struct CustomFormView: View { var body: some View { ScrollView { VStack(spacing: 0) { customRow("Row 1") Divider() .padding(.leading) customRow("Row 2") Divider() .padding(.leading) customRow("Row 3") } .background(.background) .scenePadding(.horizontal) } .background(Color(uiColor: .systemGroupedBackground)) } private func customRow(_ title: LocalizedStringKey) -> some View { Text(title) .frame(maxWidth: .infinity, minHeight: 44, alignment: .leading) .padding(.horizontal) } } Note in UIKit, UITableViewController with the inset grouped style has the same layout as Form. A custom view hierarchy can achieve the exact same placement/padding/margins by following these steps: create a scroll view and a content view, set preservesSuperviewLayoutMargins = true on both views, constrain the scroll view to the root view on all edges, constrain the content view to the scrollView.contentLayoutGuide on all edges, constrain the content view width anchor to the scrollView.frameLayoutGuide.widthAnchor, then constrain subviews of the content view to the contentView.layoutMarginsGuide. So I know how to do it in UIKit, how do we in SwiftUI? Thanks!
Topic: UI Frameworks SubTopic: SwiftUI
3
1
165
1d
Bar layout guides are offset by the vertical-bar inset for views inside a UINavigationController when verticalBarEdge is leading
Configuration: Xcode 27.1 (27A9269) iOS 27.1 Simulator (24A94401), iPhone Duo macOS 27.2 (26B5086k) On iOS 27.1, when the vertical bar is on the leading edge, UINavigationController adds a leading safe area inset for the vertical bar (84 pt on iPhone Duo outer display) that the window itself does not have. Bar layout guides (UIView.layoutGuide(for: .bar(onEdge:extent:))) requested from any view inside the navigation controller are then resolved against that inset instead of the actual bar strip: Left-edge bar guides are pinned to x = 84 (the inner edge of the inset) instead of being centered in the vertical bar strip. Top/bottom bar guides start at x = 84. This part matches the mirrored trailing-edge behavior. The same guides requested from a view outside the navigation controller (the window's root view) put the left-edge guides correctly inside the strip, centered at x = 48. They are exact mirrors of the trailing-edge results. With the vertical bar on the trailing edge, everything is consistent: the window itself carries the 84 pt trailing inset and an active occlusion reserved region for the vertical status bar, and guides are identical whether requested from inside or outside the navigation controller. So the leading and trailing configurations are asymmetric. With a trailing bar, the vertical-bar inset lives on the window. With a leading bar, it exists only on UINavigationController's content, and the bar layout region math appears to treat it as an ordinary safe-area inset to avoid rather than as the bar strip. This happens with the navigation bar hidden via setNavigationBarHidden(true, animated: false). (Hiding it by setting navigationBar.isHidden = true additionally shifts the top guides down, which we assume is expected since the controller still considers the bar visible.) Steps to reproduce: Build and run the attached sample on the iPhone Duo simulator (iOS 27.1), outer display, portrait. Put the app in the configuration where traitCollection.verticalBarEdge == .leading. With "Plain root" selected, note the yellow (left-edge) bar guides: 22/44/88 pt bands share one center line inside the leading strip. Tap the center button and select "UINavigationController" (the navigation bar is hidden with setNavigationBarHidden(true, animated: false)). Observe the yellow bands and check the console output (lines prefixed with [BarLayoutGuidePlayground]). Repeat steps 3–5 with verticalBarEdge == .trailing and compare the green (right-edge) bands. Expected results: Bar layout guides resolve the same way for leading and trailing vertical bars, and the same way whether the requesting view is the window root or a child of UINavigationController. With a leading bar, the left-edge guides should be centered in the vertical bar strip (x = 37 / 26 / 4 for extents 22 / 44 / 88 in a 469 pt wide window), mirroring the trailing results (x = 410 / 399 / 377). Actual results: With a leading bar, inside UINavigationController: view.safeAreaInsets = (top: 0, left: 84, bottom: 34, right: 0) window.safeAreaInsets = (top: 0, left: 0, bottom: 34, right: 0) left 22: (84, 16, 22, 619) left 44: (84, 16, 44, 619) left 88: (84, 16, 88, 619) top 22: (84, 37, 376.33, 22) Same guides requested from the window's root view: left 22: (37, 16, 22, 619) left 44: (26, 16, 44, 619) left 88: (4, 16, 88, 619) top 22: (16, 37, 444.33, 22) With a trailing bar (identical from both views): view.safeAreaInsets = (top: 0, left: 0, bottom: 34, right: 84) window.safeAreaInsets = (top: 0, left: 0, bottom: 34, right: 84) occlusion reserved region (active): (385, 0, 84, 120) right 22: (410, 120, 22, 515) right 44: (399, 120, 44, 515) right 88: (377, 120, 88, 515) top 22: (8.67, 37, 376.33, 22) With a leading bar there is no active occlusion region for the status bar, and the window has no leading inset, yet UINavigationController adds one. Sample project
Topic: UI Frameworks SubTopic: UIKit
3
2
151
1d
How to separate/add space between Liquid Glass toolbar items when using ToolbarOverflowMenu
When optimizing for iPhone Duo (and in general) I understand the recommendation is to replace custom More (...) menus with the system overflow menu, otherwise it's possible you can see two (...) buttons or get the custom menu nested inside the system overflow menu. Eek. With the following code, both (+) and (...) are unexpectedly inside one shared Liquid Glass background. How do you separate / add space between them or is this a bug, if so is there a workaround? struct ContentView: View { var body: some View { NavigationStack { Text("Hello, World") .toolbar { ToolbarItem { Button("Add", systemImage: "plus") { } } ToolbarSpacer(.fixed) ToolbarOverflowMenu { Button("Settings", systemImage: "gearshape") { } } } } } } Here's my original code that display two separate buttons as expected: struct ContentView: View { var body: some View { NavigationStack { Text("Hello, World") .toolbar { ToolbarItem { Button("Add", systemImage: "plus") { } } ToolbarSpacer(.fixed) ToolbarItem { Menu { Button("Settings", systemImage: "gearshape") { } } label: { Label("More", systemImage: "ellipsis") } } } } } } Why do I care you might ask? When the user turns on filters in my app, a filter toolbar item is shown, and I want the (+) to remain separate from the grouped filter and more buttons. (+) is like the primary action that should stand alone, like it does in the Wallet app.
Topic: UI Frameworks SubTopic: SwiftUI
3
1
93
1d
Can a custom keyboard extend its background into the system-owned top and bottom area
Hello Apple Developer Community, I am developing Keyboard Atelier, a Korean custom keyboard built with Swift, UIKit, and UIInputViewController. Is there a supported way to apply a user-selected background color or image across the entire keyboard presentation, including the surrounding system-owned areas? Problem On an iPhone, we observe a strip above our keyboard extension’s visible content and a separate bottom area containing the system globe and dictation controls. When we apply a custom background to our extension, these surrounding areas retain a different background. This makes our keyboard look like a rectangular panel placed inside a separate system frame. Our product lets users customize keycaps and keyboard backgrounds. We want their selected color or image to appear continuous across the entire keyboard presentation. What we have tested We compared an opaque white root-view background with a clear root-view background in an isolated simulator test. With the opaque background, the boundaries above and below the extension were visible. Removing our own top padding did not eliminate the upper strip. Setting the root view’s backgroundColor to UIColor.clear made the backgrounds appear visually continuous in both light and dark appearances. However, this only reveals the default system background. It does not Questions Is there a public API or supported configuration that lets a custom keyboard specify the background color of the surrounding system-owned areas? Can a custom keyboard supply a background image that extends into those areas, including beneath the system globe and dictation controls? If neither is supported, what is the documented boundary of background customization for a keyboard extension? Is Feedback Assistant the appropriate place to request this capability? iOS should retain control of the system buttons, including their behavior, accessibility, touch targets, and contrast adjustments. We are asking to customize the background behind them while preserving their functionality. The solution must be suitable for App Store distribution and work when the keyboard is used in other apps, without requiring changes to those host apps. Reproduction steps Enable the custom keyboard in Settings > General > Keyboard > Keyboards. Open a UITextView in the containing app. Switch to the custom keyboard. Set the keyboard extension’s root-view background to an opaque white color while using dark appearance. Observe the different backgrounds above and below the extension’s content. Compare this with a build using UIColor.clear for the root-view background. Implementation Swift and UIKit UIInputViewController keyboard extension Test host: a UIKit UITextView in the containing app Light and dark appearances tested RequestsOpenAccess = false Please point me to any relevant API or documentation, or clarify whether this would require a new API. Thank you.
Topic: UI Frameworks SubTopic: UIKit
0
0
50
1d
CarPlay CPListImageRowItem causes Inverted Scrolling and Side Button malfunction
In my CarPlaySceneDelegate.swift, I have two tabs: The first tab uses a CPListImageRowItem with a CPListImageRowItemRowElement. The scroll direction is inverted, and the side button does not function correctly. The second tab uses multiple CPListItem objects. There are no issues: scrolling works in the correct direction, and the side button behaves as expected. Steps To Reproduce Launch the app. Connect to CarPlay. In the first tab, scroll up and down, then use the side button to navigate. In the second tab, scroll up and down, then use the side button to navigate. As observed, the scrolling behavior is different between the two tabs. Code Example: import CarPlay import UIKit class CarPlaySceneDelegate: UIResponder, CPTemplateApplicationSceneDelegate { var interfaceController: CPInterfaceController? func templateApplicationScene( _ templateApplicationScene: CPTemplateApplicationScene, didConnect interfaceController: CPInterfaceController ) { self.interfaceController = interfaceController downloadImageAndSetupTemplates() } func templateApplicationScene( _ templateApplicationScene: CPTemplateApplicationScene, didDisconnectInterfaceController interfaceController: CPInterfaceController ) { self.interfaceController = nil } private func downloadImageAndSetupTemplates() { let urlString = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRcYUjd1FYkF04-8Vb7PKI1mGoF2quLPHKjvnR7V4ReZR8UjW-0NJ_kC7q13eISZGoTCLHaDPVbOthhH9QNq-YA0uuSUjfAoB3PPs1aXQ&s=10" guard let url = URL(string: urlString) else { setupTemplates(with: UIImage(systemName: "photo")!) return } URLSession.shared.dataTask(with: url) { [weak self] data, _, _ in let image: UIImage if let data = data, let downloaded = UIImage(data: data) { image = downloaded } else { image = UIImage(systemName: "photo")! } DispatchQueue.main.async { self?.setupTemplates(with: image) } }.resume() } private func setupTemplates(with image: UIImage) { // Tab 1 : un seul CPListImageRowItem avec 12 CPListImageRowItemRowElement let elements: [CPListImageRowItemRowElement] = (1...12).map { index in CPListImageRowItemRowElement(image: image, title: "test \(index)", subtitle: nil) } let rowItem = CPListImageRowItem(text: "Images", elements: elements, allowsMultipleLines: true) rowItem.listImageRowHandler = { item, elementIndex, completion in print("tapped element \(elementIndex)") completion() } let tab1Section = CPListSection(items: [rowItem]) let tab1Template = CPListTemplate(title: "CPListImageRowItemRowElement", sections: [tab1Section]) // Tab 2 : 12 CPListItem simples let tab2Items: [CPListItem] = (1...12).map { index in let item = CPListItem(text: "Item \(index)", detailText: "Detail \(index)") item.handler = { _, completion in print("handler Tab 2") completion() } return item } let tab2Section = CPListSection(items: tab2Items) let tab2Template = CPListTemplate(title: "CPListItem", sections: [tab2Section]) // CPTabBarTemplate avec les deux tabs let tabBar = CPTabBarTemplate(templates: [tab1Template, tab2Template]) interfaceController?.setRootTemplate(tabBar, animated: true) } } Here is a quick video:
8
1
1k
1d
About wallpaper app for iPhone Duo
I'm building a wallpaper app for iPhone Duo. The outer display is portrait (1398×2034), and the unfolded inner display is landscape (2670×1878). My wallpapers are portrait images — for example, a person centered in the frame. When the user unfolds the device and the screen changes from portrait to landscape, how does iOS adapt the wallpaper? Specifically: Does it crop a landscape region from the portrait image (which could cut off the subject)? Does it preserve the focal point the user chose when setting the wallpaper, keeping the subject in frame? Or can separate images be assigned to the outer and inner displays? I need to understand this behavior to decide what compositions to offer in my app.
Topic: UI Frameworks SubTopic: SwiftUI
1
0
52
1d
Modal on trailing
Hi I want to open a modal sheet so it's centered when the iPhone Duo is opened, but on the right side of the screen (trailing) when it's half-closed. But it seems like the "placement" property of the sheetPresentationController applies in all configurations. Is there a way to set a placement "order" (centered if possible, then trailing, then leading) ?
Topic: UI Frameworks SubTopic: UIKit
2
0
103
1d
A Summary of the iPhone Duo Group Lab
Group Labs are a unique opportunity for the community to submit questions directly to a panel of Apple engineers and designers. Here are the highlights from the iPhone Duo Group Labs: How should apps preserve navigation and UI state when switching between the inner and outer displays? Treat display transitions as size-class and trait changes, not a scene disconnect or app termination; your process stays alive. For more information, see Prepare your app for iPhone Duo. For state that must survive a scene disconnect/reconnect, implement stateRestorationActivity(for:) to save an NSUserActivity Restoring your app's state. Do multiple instances of the same app on iPhone Duo share UserDefaults/@AppStorage state? Multiple instances of your app's UI on iPhone Duo behave similarly to multi-window support on iPadOS. To learn more, see Leverage multiple displays and scenes on iPhone Duo. Both UserDefaults and AppStorage are app-wide, not per-window, stores. If a full-screen app on the inner display is closed, does it move to the outer display or get backgrounded? iPhone Duo honors UIRequiresFullScreen and apps adapt in place as the device opens and closes rather than backgrounding. To learn more, watch Prepare your app for iPhone Duo. How should apps preserve state — text input, scroll position, video playback, camera sessions — during hinge angle transitions? For example, when a LazyVGrid's column count changes because the device folds, does SwiftUI preserve scroll position automatically, or should you use scrollPosition(id:)? The system generally preserves text input and scroll position automatically since hinge angle changes are represented as size-class and trait updates, not a scene disconnect or app termination. This applies even to cases like a LazyVGrid column-count change triggered by opening or closing the device — apps typically don't need to manually manage scroll position with scrollPosition(id:anchor:) for this transition. For more info, see Prepare your app for iPhone Duo. How can apps preserve what someone is doing when switching displays or folding/unfolding? Treat this as a resize/trait-change event, not app teardown — your process keeps running as size classes change. See Prepare your app for iPhone Duo to learn more. For scenes that actually disconnect and reconnect, implement stateRestorationActivity(for:) to save an NSUserActivity Restoring your app's state. How does actively playing video behave through the hinge angle animation? The system generally preserves video playback and player position automatically since hinge angle changes are represented as size-class and trait updates, not a scene disconnect or app termination. AVKit will scale and resize the video automatically. If a user folds or unfolds the device mid-checkout, what does the system preserve automatically, and what should the app manage itself to avoid lost input or duplicate requests? When someone opens or closes an iPhone Duo, the system represents this as a size-class and trait collection change, not a scene disconnect or app teardown, so in-memory state like input fields typically persists automatically since the app’s process keeps running. For more info, see Prepare your app for iPhone Duo. How should apps handle the keyboard and text input when the device folds or unfolds while typing? As iPhone Duo folds or unfolds, the available screen geometry and framing change. Ensure your app adopts standard layout controls, containers, and size classes to handle resizability gracefully across all poses. When a text field becomes first responder, the system automatically shows the keyboard and binds its input to the text field. Because the appearance of the keyboard has the potential to obscure portions of your user interface, you should update your interface as needed to ensure that the text field being edited remains visible. Use keyboard notifications such as keyboardWillShowNotification, keyboardWillHideNotification, and keyboardWillChangeFrameNotification to detect the appearance and disappearance of the keyboard and to make necessary changes to your interface layout. To learn more, see UITextField. If someone is typing and closes iPhone Duo, does the keyboard/editing session survive the hinge transition, or does it get a new scene? When a user types and closes iPhone Duo, the active editing session and keyboard do not get a completely new scene. Instead, the app undergoes a dynamic resizing and transitions from the inner display to the compact outer display, maintaining the existing scene and application state. For more info, watch Prepare your app for iPhone Duo.
Replies
16
Boosts
0
Views
899
Activity
2d
Supported way to put an iPhone Duo simulator into the unfolded state programmatically
The Duo simulator boots showing only the outer display: the window is fixed at 382×644 pt and our layout classifier always reports the compact stack mode. We measured this on two separate clean boots (shutdown, erase, boot). xcrun simctl help lists no subcommand for folding, posture, or selecting the inner display — we read the full list. xcrun simctl io screenshot does reveal a second display (LCD-1, 2007×2853 px, aspect 0.70, close to the 669×951 inner portrait size). Unfolding manually in the Simulator UI works and the app then renders the two-column layout correctly, but we could not find a programmatic equivalent. Is there a supported way to unfold a Duo simulator from the command line or from XCTest?
Topic: UI Frameworks SubTopic: SwiftUI
Replies
3
Boosts
3
Views
688
Activity
14h
sidebarAdaptable Design Problem
This is what Apple's Destination Video Sample App looks like on iPhone Duo built with SDK 27.1 beta. Two things: Items that should not appear in the tab bar appear. There is no sidebar for iPhone Duo. So my problem is: is this a bug or a design on purpose? Will sidebarAdaptable gets a sidebar on iPhone Duo? Or at least, how to hide these things that should only appear in the sidebar? The sample app uses .defaultVisibility(, for:) and .hidden() but obviously none of these takes effect.
Topic: UI Frameworks SubTopic: SwiftUI
Replies
0
Boosts
0
Views
147
Activity
18h
Enable iPhone Duo Upside Down Orientation
Ever since the iPhone X, upside-down orientation on the iPhone has been disabled by design. I haven't found any official documentation explaining why, but my guess is it has to do with Face ID and the top notch. However, now that the iPhone Duo has no Face ID or notch—and includes reserved occlusion regions—why not enable upside-down rotation? As of iOS 27.1, it remains disabled. Leaving it turned off only confuses users, making them think their favorite apps are frozen when they won't rotate.
Topic: UI Frameworks SubTopic: SwiftUI
Replies
1
Boosts
1
Views
305
Activity
20h
iPhone Duo and the Safe-Area
I took a screenshot of the Safety Area's and Occlusions on the iPhone Duo outer display. The article Designing for iPhone Duo tells us to... Consider using the full display width for interfaces where bars aren’t necessary. Some layouts can span the full display, which works well for visual, immersive interfaces that don’t scroll, as long as nothing conflicts with the Dynamic Island or the status bar. Calculator, for example, occupies the full width of the display. You can also combine both approaches, letting a background image or header span the full width while scrollable content stays inset. The Graphics Content can easily take up the full space which can be achieved by ignoring the safe area (.ignoresSafeArea()). And knowing the iPhone Duo there is no occlusion so I can also ignore the safe area for the interactable content. However we now are entering an awkward state. Because now I need to make decisions based on a specific device. Knowing the iPhone Duo I can ignore horizontal safe area and expand to full width because there is no occlusions here, but ignoring the safe-area may result in unexpected behavior on other (future) devices which then requires me to use code that specificly targets certain devices. I wished SwiftUI had something that I could safely expand the interactable content the full width.
Topic: UI Frameworks SubTopic: SwiftUI
Replies
2
Boosts
0
Views
101
Activity
20h
iOS 27: UIApplication.shared.open fail for relative URL values that resolve to valid https URLs
A URL created with URL(string:relativeTo:) that used to work in iOS26 and below with UIApplication.shared.open stopped working in iOS27, the app has not been built yet with iOS27 SDK. Have anyone seen this issue, all the links work perfectly in iOS26 and below. We found a solution to use .absoluteURL but still want to check with the community, I havent seen any mention of this this that it will break try the below sample code import UIKit struct RelativeURLReproView: View { @State private var log = "Tap a button. Watch this log and whether Safari actually appears.\n" var body: some View { VStack(alignment: .leading, spacing: 16) { Button("Open relative URL") { openTarget(.relative) } .buttonStyle(.borderedProminent) Button("Open absoluteURL") { openTarget(.absolute) } .buttonStyle(.bordered) Button("Clear log") { log = "" } ScrollView { Text(log) .font(.system(.footnote, design: .monospaced)) .textSelection(.enabled) .frame(maxWidth: .infinity, alignment: .leading) } } .padding() } private enum ReproTarget { case relative case absolute } private func append(_ line: String) { log.append(line + "\n") print(line) } private func openTarget(_ target: ReproTarget) { log = "" let base = URL(string: "https://www.example.com")! let relative = URL(string: "about/help", relativeTo: base)! let url = (target == .relative) ? relative : relative.absoluteURL append("target: \(target == .relative ? "relative" : "absoluteURL")") append("url: \(url)") append("absoluteString: \(url.absoluteString)") append("scheme: \(url.scheme ?? "nil")") append("baseURL: \(url.baseURL?.absoluteString ?? "nil")") append("relativeString: \(url.relativeString)") append("canOpenURL: \(UIApplication.shared.canOpenURL(url))") append("Calling UIApplication.shared.open…") append("Did Safari actually appear? Check by eye.") UIApplication.shared.open(url, options: [:]) { success in Task { @MainActor in append("open completion: \(success)") } } } } #Preview { RelativeURLReproView() }
Replies
4
Boosts
0
Views
59
Activity
23h
viewDidDisappear is not called on a popped view controller when switching tabs during UITabBarController's reselect pop-to-root on iOS 27
Issue Description Hi, I would like to share an issue with UIViewController's appearance callbacks inside UITabBarController + UINavigationController on iOS 27. When a tab containing a UINavigationController with two view controllers is re-tapped, UIKit starts its built-in animated pop-to-root. On iOS 27, if the user switches to another tab while that pop animation is still in flight, the popped view controller receives viewWillDisappear: (with isMovingFromParent == true), but viewDidDisappear: is never called on it. The appearance callbacks stay unbalanced. This breaks code that relies on viewDidDisappear: + isMovingFromParent to detect that a view controller was popped. Steps to Reproduce Create a UITabBarController with two tabs. The first tab is a UINavigationController. In the first tab, push a second view controller ("Nested"). Tap the first tab item again. UIKit starts the animated pop-to-root. Immediately (while the pop animation is still running), tap the second tab item. Expected vs. Actual Behavior Expected: On iOS 26, "Nested" receives viewWillDisappear: and then viewDidDisappear:, both with isMovingFromParent == true. Actual: On iOS 27, "Nested" receives only viewWillDisappear:. viewDidDisappear: is NOT called, even though "Nested" is no longer in navigationController.viewControllers. Note: On iOS 27, if the second tab is tapped after the pop animation has finished, viewDidDisappear: is delivered correctly. The issue only occurs when the tab switch happens during the pop transition. Environment Xcode Version 27.0 iOS 27.0 iPhone 18 Pro simulator: reproduces iOS 26.0 iPhone 17 Pro simulator: does not reproduce Feedback Assistant Report ID: FB24934469 Minimal Reproduction Example // SceneDelegate.swift import UIKit class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = scene as? UIWindowScene else { return } let window = UIWindow(windowScene: windowScene) window.rootViewController = TabBarController() window.makeKeyAndVisible() self.window = window } } // TabBarController.swift import UIKit final class TabBarController: UITabBarController { override func viewDidLoad() { super.viewDidLoad() let firstNav = UINavigationController(rootViewController: HomeViewController()) firstNav.tabBarItem = UITabBarItem(title: "First", image: UIImage(systemName: "house"), tag: 0) let second = LoggingViewController(name: "Second") second.tabBarItem = UITabBarItem(title: "Second", image: UIImage(systemName: "star"), tag: 1) viewControllers = [firstNav, second] } } class LoggingViewController: UIViewController { let name: String init(name: String) { self.name = name super.init(nibName: nil, bundle: nil) title = name } required init?(coder: NSCoder) { fatalError() } override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .systemBackground } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) print("[\(name)] viewWillDisappear isMovingFromParent=\(isMovingFromParent)") } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) print("[\(name)] viewDidDisappear isMovingFromParent=\(isMovingFromParent)") } } final class HomeViewController: LoggingViewController { init() { super.init(name: "Home") } required init?(coder: NSCoder) { fatalError() } override func viewDidLoad() { super.viewDidLoad() navigationItem.rightBarButtonItem = UIBarButtonItem( title: "Push", primaryAction: UIAction { [weak self] _ in self?.navigationController?.pushViewController(LoggingViewController(name: "Nested"), animated: true) } ) } }
Topic: UI Frameworks SubTopic: UIKit
Replies
0
Boosts
0
Views
33
Activity
23h
Repeated Swift error breakpoint stops in system frameworks during AppKit startup and window creation
I debug an Objective-C++ AppKit application in CLion. The application runs normally, but a “When any is thrown” breakpoint stops repeatedly during startup and window creation, making it difficult to debug. One stop occurs before any window is created: [NSApplication run] → finishLaunching → _customizeMainMenu → [NSTextView _supportsWritingTools] → GenerativeModels → JSONDecoder → swift_willThrow. LLDB identifies a decoding frame as GenerativeModels.AvailabilityStore.ReadinessEntry.Criteria.init(from:). Other stops occur while NSDocumentController attempts to reopen documents, and while AppKit resets gesture recognizers during NSWindow creation. All the supplied stops reach swift_willThrow; the app continues after resuming. Are these expected handled errors? Is there a supported way to prevent the startup Writing Tools check from throwing? I can provide the complete stacks and a minimal reproduction if helpful. I'm on MacOS Tahoe 26.6.2 (25G83) Xcode 26.4.1 - Build version 17E202 Apple clang version 21.0.0 (clang-2100.0.123.102) I'm building from within CLion 2026.2.3 and using the bundled LLDB (21.1.7), but the problem also occurs when using the one from XCode (21.0) Disabling Apple Intelligence in the OS settings does not help.
Topic: UI Frameworks SubTopic: AppKit
Replies
0
Boosts
0
Views
26
Activity
1d
CALayer with valid contents and correct configuration is excluded from window compositing on Apple Silicon (works fine on Intel)
macOS/Hardware details: macOS version: 27.0 (build 26A428) Hardware: Apple Silicon Mac (arm64) App architecture: Native arm64 Xcode/SDK: Built against MacOSX27.0 SDK Deployment target: MACOSX_DEPLOYMENT_TARGET = 26.0 Regression history: Same app/codebase previously built and ran correctly on macOS 13 (Ventura), Intel — issue only appears after migrating the build to Apple Silicon; no changes were made to the affected view's drawing or layer-configuration code between the two builds We have a custom, layer-backed NSView (part of a hand-rolled tree/list control that draws its own content via Core Graphics into the layer's contents) that renders completely blank on screen on Apple Silicon Macs, while an adjacent sibling view using the identical view class, drawing code, and layer configuration renders correctly. Using lldb and Xcode's View Debugger against the live process, we've confirmed: The layer's actual backing content is correct: capturing it directly via -renderInContext: produces the expected fully-drawn image (text and icons all present). Every inspectable property of the broken view/layer (hidden, alphaValue, opaque, wantsLayer, isFlipped/isGeometryFlipped, zPosition, masksToBounds, contentsScale, mask, transform, backgroundColor, contents, sublayers, superlayer) is identical to the working sibling view — no configuration difference exists anywhere. The layer's superlayer link is intact and points to the correct parent, ruling out a detached/orphaned layer. Standard remediation attempts — setNeedsDisplay:, displayIfNeeded, toggling wantsLayer, detaching/reattaching the view from its superview, changing zPosition — all have zero effect. Most notably, directly setting layer.backgroundColor to an opaque solid color on the live, correctly-connected layer (verified via property readback) produces no visible change on screen at all. Because even an unconditional background color change is not reflected, the layer appears to be excluded from what's actually sent to the window server for compositing, rather than simply failing to draw updated content. Since all inspectable state is correct and identical to a working sibling view, we've been unable to identify any application-level cause. The view remains fully interactive — clicks and hit-testing resolve correctly to the right underlying data — only the visual output is missing. Are there known Apple Silicon-specific changes to CALayer/NSView compositing (window server layer inclusion, contentsScale/backing-store allocation, or layer-backed view promotion) that could cause a fully valid, connected CALayer with correct contents to be silently dropped from the composited frame? Any suggestions for further diagnostic tools (e.g. Quartz Debug, CARenderServer logging, or WindowServer compositing traces) to narrow this down further would help.
Topic: UI Frameworks SubTopic: AppKit
Replies
0
Boosts
0
Views
11
Activity
1d
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
0
Boosts
0
Views
46
Activity
1d
Charts are broken with Xcode 27, Plotting multiple lines
Hi, Charts—specifically those with multiple lines—are broken in Xcode 27. First, I spotted the bug in my program, and then I checked your example. Your own example Plotting-multiple-lines is not working correctly anymore. It shows 1 line or sometimes no lines at all, depending on the order of the data. It depends on how the data is passed to the chart. If the data is passed as separate series, it works. In Visualizing your app’s data it works, but the data is passed as described before. Don't follow Microslop: have the AI ​​generate the code and then skip the tests. This is a serious bug that requires a lot of work to rearrange the data, just to work around the issue. Christian
Replies
0
Boosts
0
Views
218
Activity
1d
App Intents and the Document App Xcode Template
I’m working on an app that deals with a list of text items, so I started with the document app template in Xcode. I have the app basically doing what I want it to do, but I want to be a good ecosystem citizen, so I’d like to conform to app intents. I think that app intents will able to do what I want - accepting text and passing it back out - but I can’t figure out how to access the document outside of my content view and associated subviews. Any guidance would be appreciated. Thank you, Don Carlile
Replies
1
Boosts
0
Views
400
Activity
1d
macOS 26.7: a side Dock prevents quarter tiling at the adjacent upper corner
I found that the failing corner in native macOS window tiling changes with the Dock position. With the Dock on the right, the upper-right corner produces the right half instead of a quarter. With the Dock on the left, the upper-left corner produces the left half instead of a quarter. With the Dock at the bottom, all four corners produce quarters. Apple's macOS Tahoe guide describes dragging to any corner as a way to tile a window there. Configuration Mac mini Mac14,12, Apple M2 Pro macOS Tahoe 26.7 (25G229) One external iiyama PL4071UH (ProLite X4071UHSU) display, with a [native panel resolution of 3840 × 2160]; no adjacent display and mirroring off. A 3840 × 2160 mode is available in macOS, but it was not the mode used for these measurements. Active macOS display mode reported by CGDisplayMode and System Information: 3008 × 1692 pixels at 60 Hz; the interface “looks like” 1504 × 846 points (2× backing scale). This is a scaled configuration on the 4K display. NSScreen.frame: 1504 × 846 points. NSScreen.visibleFrame with the Dock on the right: approximately 1456 × 816 points (about 48 points removed at the right for the Dock and 30 at the top for the menu bar). macOS reports Television: Yes for this display and exposes an Underscan control in Displays settings. The slider appeared at the “No” end during inspection; its effect on this tiling behavior has not been tested. Dock position changed between right, left, and bottom for the comparison below Dock auto-hide is currently off (com.apple.dock autohide = 0) Native drag-to-edge tiling and the Option-key tiling accelerator enabled; tiled window margins disabled Upper-right Hot Corner configured without a modifier key during the right-Dock measurement Steps to reproduce Open a blank, resizable TextEdit window and enable native drag-to-edge tiling. Set the Dock position to Right in System Settings → Desktop & Dock. Drag the window by its title bar to each screen corner and release after the tiling preview appears. Set the Dock position to Left and repeat. Set the Dock position to Bottom and repeat. Dock-position comparison Dock position Upper-left corner Upper-right corner Lower corners Right quarter right half quarters Left left half quarter quarters Bottom quarter quarter quarters The left- and bottom-Dock comparisons are direct user observations. The right-Dock case was also measured programmatically as described below. This pattern points to a side-Dock interaction with detection of the adjacent upper corner; the internal cause is not yet established. The display's scaled mode and its classification as a television are additional variables worth recording. Neither has been isolated as a cause: the controlled change so far is the Dock position. A useful follow-up would be to repeat the same corner tests at another display mode, including 3840 × 2160, with the Dock kept on the same side, and to record the Underscan setting. Instrumented result with Dock on the right I sampled NSEvent.mouseLocation every 20 ms, used CGEventSource.buttonState to identify the release, and read the window bounds using CGWindowListCopyWindowInfo about 0.6 seconds later. The same TextEdit window ID was observed for all four corner tests. Pointer and window coordinates below use the top-left of the display as (0, 0); dimensions are in macOS points. Release corner Pointer (x, y) Window (x, y, width, height) Result Top left (0, 0) (-1, 30, 727, 409) quarter Top right (1503.98, 0) (727, 30, 728, 816) RIGHT HALF Bottom left (0, 845.98) (-1, 438, 727, 409) quarter Bottom right (1503.98, 845.98) (727, 438, 728, 409) quarter At the upper-right release, the pointer is effectively at the screen's rightmost x coordinate and at y = 0. The resulting window is 816 points high, compared with 409 points for each quarter tile. The Hot Corner did not prevent the pointer from reaching that coordinate. Expected result Dragging to any of the four corners should produce the corresponding quarter regardless of whether the Dock is on the right, left, or bottom.
Topic: UI Frameworks SubTopic: General Tags:
Replies
0
Boosts
0
Views
52
Activity
1d
How to implement correct horizontal padding for iPhone Duo
The iPhone Duo outer screen displays a vertical bar on the right edge with view contents inset. A SwiftUI Form displays an appropriate amount of leading padding but 0 padding on the trailing edge, since the vertical bar provides some visual margins already that looks nice. I have a view that looks kind of like a form, multiple stacked text fields, that should align the same way. I used scenePadding to achieve which looks correct on iPhone 18 Pro perfectly aligned with Form, but on iPhone Duo there is extra trailing padding. It doesn't align with my Edit button that remains in the horizontal axis navigation bar (and it is not inset enough on the leading edge, off by a few pixels, interestingly). Note when you unfold it and add the app on the left side in Split View, the vertical bar is on the leading edge, in which case there's too much padding on the leading edge. How can I achieve the correct layout padding/margins? iPhone 18 Pro vs iPhone Duo: My actual app: struct ContentView: View { var body: some View { TabView { NavigationStack { SystemFormView() .navigationTitle("System Form") } .tabItem { Label("System Form", systemImage: "list.bullet.rectangle") } NavigationStack { CustomFormView() .navigationTitle("Custom Form") } .tabItem { Label("Custom Form", systemImage: "rectangle.3.group") } } } } private struct SystemFormView: View { var body: some View { Form { Text("Row 1") Text("Row 2") Text("Row 3") } } } private struct CustomFormView: View { var body: some View { ScrollView { VStack(spacing: 0) { customRow("Row 1") Divider() .padding(.leading) customRow("Row 2") Divider() .padding(.leading) customRow("Row 3") } .background(.background) .scenePadding(.horizontal) } .background(Color(uiColor: .systemGroupedBackground)) } private func customRow(_ title: LocalizedStringKey) -> some View { Text(title) .frame(maxWidth: .infinity, minHeight: 44, alignment: .leading) .padding(.horizontal) } } Note in UIKit, UITableViewController with the inset grouped style has the same layout as Form. A custom view hierarchy can achieve the exact same placement/padding/margins by following these steps: create a scroll view and a content view, set preservesSuperviewLayoutMargins = true on both views, constrain the scroll view to the root view on all edges, constrain the content view to the scrollView.contentLayoutGuide on all edges, constrain the content view width anchor to the scrollView.frameLayoutGuide.widthAnchor, then constrain subviews of the content view to the contentView.layoutMarginsGuide. So I know how to do it in UIKit, how do we in SwiftUI? Thanks!
Topic: UI Frameworks SubTopic: SwiftUI
Replies
3
Boosts
1
Views
165
Activity
1d
Bar layout guides are offset by the vertical-bar inset for views inside a UINavigationController when verticalBarEdge is leading
Configuration: Xcode 27.1 (27A9269) iOS 27.1 Simulator (24A94401), iPhone Duo macOS 27.2 (26B5086k) On iOS 27.1, when the vertical bar is on the leading edge, UINavigationController adds a leading safe area inset for the vertical bar (84 pt on iPhone Duo outer display) that the window itself does not have. Bar layout guides (UIView.layoutGuide(for: .bar(onEdge:extent:))) requested from any view inside the navigation controller are then resolved against that inset instead of the actual bar strip: Left-edge bar guides are pinned to x = 84 (the inner edge of the inset) instead of being centered in the vertical bar strip. Top/bottom bar guides start at x = 84. This part matches the mirrored trailing-edge behavior. The same guides requested from a view outside the navigation controller (the window's root view) put the left-edge guides correctly inside the strip, centered at x = 48. They are exact mirrors of the trailing-edge results. With the vertical bar on the trailing edge, everything is consistent: the window itself carries the 84 pt trailing inset and an active occlusion reserved region for the vertical status bar, and guides are identical whether requested from inside or outside the navigation controller. So the leading and trailing configurations are asymmetric. With a trailing bar, the vertical-bar inset lives on the window. With a leading bar, it exists only on UINavigationController's content, and the bar layout region math appears to treat it as an ordinary safe-area inset to avoid rather than as the bar strip. This happens with the navigation bar hidden via setNavigationBarHidden(true, animated: false). (Hiding it by setting navigationBar.isHidden = true additionally shifts the top guides down, which we assume is expected since the controller still considers the bar visible.) Steps to reproduce: Build and run the attached sample on the iPhone Duo simulator (iOS 27.1), outer display, portrait. Put the app in the configuration where traitCollection.verticalBarEdge == .leading. With "Plain root" selected, note the yellow (left-edge) bar guides: 22/44/88 pt bands share one center line inside the leading strip. Tap the center button and select "UINavigationController" (the navigation bar is hidden with setNavigationBarHidden(true, animated: false)). Observe the yellow bands and check the console output (lines prefixed with [BarLayoutGuidePlayground]). Repeat steps 3–5 with verticalBarEdge == .trailing and compare the green (right-edge) bands. Expected results: Bar layout guides resolve the same way for leading and trailing vertical bars, and the same way whether the requesting view is the window root or a child of UINavigationController. With a leading bar, the left-edge guides should be centered in the vertical bar strip (x = 37 / 26 / 4 for extents 22 / 44 / 88 in a 469 pt wide window), mirroring the trailing results (x = 410 / 399 / 377). Actual results: With a leading bar, inside UINavigationController: view.safeAreaInsets = (top: 0, left: 84, bottom: 34, right: 0) window.safeAreaInsets = (top: 0, left: 0, bottom: 34, right: 0) left 22: (84, 16, 22, 619) left 44: (84, 16, 44, 619) left 88: (84, 16, 88, 619) top 22: (84, 37, 376.33, 22) Same guides requested from the window's root view: left 22: (37, 16, 22, 619) left 44: (26, 16, 44, 619) left 88: (4, 16, 88, 619) top 22: (16, 37, 444.33, 22) With a trailing bar (identical from both views): view.safeAreaInsets = (top: 0, left: 0, bottom: 34, right: 84) window.safeAreaInsets = (top: 0, left: 0, bottom: 34, right: 84) occlusion reserved region (active): (385, 0, 84, 120) right 22: (410, 120, 22, 515) right 44: (399, 120, 44, 515) right 88: (377, 120, 88, 515) top 22: (8.67, 37, 376.33, 22) With a leading bar there is no active occlusion region for the status bar, and the window has no leading inset, yet UINavigationController adds one. Sample project
Topic: UI Frameworks SubTopic: UIKit
Replies
3
Boosts
2
Views
151
Activity
1d
How to separate/add space between Liquid Glass toolbar items when using ToolbarOverflowMenu
When optimizing for iPhone Duo (and in general) I understand the recommendation is to replace custom More (...) menus with the system overflow menu, otherwise it's possible you can see two (...) buttons or get the custom menu nested inside the system overflow menu. Eek. With the following code, both (+) and (...) are unexpectedly inside one shared Liquid Glass background. How do you separate / add space between them or is this a bug, if so is there a workaround? struct ContentView: View { var body: some View { NavigationStack { Text("Hello, World") .toolbar { ToolbarItem { Button("Add", systemImage: "plus") { } } ToolbarSpacer(.fixed) ToolbarOverflowMenu { Button("Settings", systemImage: "gearshape") { } } } } } } Here's my original code that display two separate buttons as expected: struct ContentView: View { var body: some View { NavigationStack { Text("Hello, World") .toolbar { ToolbarItem { Button("Add", systemImage: "plus") { } } ToolbarSpacer(.fixed) ToolbarItem { Menu { Button("Settings", systemImage: "gearshape") { } } label: { Label("More", systemImage: "ellipsis") } } } } } } Why do I care you might ask? When the user turns on filters in my app, a filter toolbar item is shown, and I want the (+) to remain separate from the grouped filter and more buttons. (+) is like the primary action that should stand alone, like it does in the Wallet app.
Topic: UI Frameworks SubTopic: SwiftUI
Replies
3
Boosts
1
Views
93
Activity
1d
Can a custom keyboard extend its background into the system-owned top and bottom area
Hello Apple Developer Community, I am developing Keyboard Atelier, a Korean custom keyboard built with Swift, UIKit, and UIInputViewController. Is there a supported way to apply a user-selected background color or image across the entire keyboard presentation, including the surrounding system-owned areas? Problem On an iPhone, we observe a strip above our keyboard extension’s visible content and a separate bottom area containing the system globe and dictation controls. When we apply a custom background to our extension, these surrounding areas retain a different background. This makes our keyboard look like a rectangular panel placed inside a separate system frame. Our product lets users customize keycaps and keyboard backgrounds. We want their selected color or image to appear continuous across the entire keyboard presentation. What we have tested We compared an opaque white root-view background with a clear root-view background in an isolated simulator test. With the opaque background, the boundaries above and below the extension were visible. Removing our own top padding did not eliminate the upper strip. Setting the root view’s backgroundColor to UIColor.clear made the backgrounds appear visually continuous in both light and dark appearances. However, this only reveals the default system background. It does not Questions Is there a public API or supported configuration that lets a custom keyboard specify the background color of the surrounding system-owned areas? Can a custom keyboard supply a background image that extends into those areas, including beneath the system globe and dictation controls? If neither is supported, what is the documented boundary of background customization for a keyboard extension? Is Feedback Assistant the appropriate place to request this capability? iOS should retain control of the system buttons, including their behavior, accessibility, touch targets, and contrast adjustments. We are asking to customize the background behind them while preserving their functionality. The solution must be suitable for App Store distribution and work when the keyboard is used in other apps, without requiring changes to those host apps. Reproduction steps Enable the custom keyboard in Settings > General > Keyboard > Keyboards. Open a UITextView in the containing app. Switch to the custom keyboard. Set the keyboard extension’s root-view background to an opaque white color while using dark appearance. Observe the different backgrounds above and below the extension’s content. Compare this with a build using UIColor.clear for the root-view background. Implementation Swift and UIKit UIInputViewController keyboard extension Test host: a UIKit UITextView in the containing app Light and dark appearances tested RequestsOpenAccess = false Please point me to any relevant API or documentation, or clarify whether this would require a new API. Thank you.
Topic: UI Frameworks SubTopic: UIKit
Replies
0
Boosts
0
Views
50
Activity
1d
CarPlay CPListImageRowItem causes Inverted Scrolling and Side Button malfunction
In my CarPlaySceneDelegate.swift, I have two tabs: The first tab uses a CPListImageRowItem with a CPListImageRowItemRowElement. The scroll direction is inverted, and the side button does not function correctly. The second tab uses multiple CPListItem objects. There are no issues: scrolling works in the correct direction, and the side button behaves as expected. Steps To Reproduce Launch the app. Connect to CarPlay. In the first tab, scroll up and down, then use the side button to navigate. In the second tab, scroll up and down, then use the side button to navigate. As observed, the scrolling behavior is different between the two tabs. Code Example: import CarPlay import UIKit class CarPlaySceneDelegate: UIResponder, CPTemplateApplicationSceneDelegate { var interfaceController: CPInterfaceController? func templateApplicationScene( _ templateApplicationScene: CPTemplateApplicationScene, didConnect interfaceController: CPInterfaceController ) { self.interfaceController = interfaceController downloadImageAndSetupTemplates() } func templateApplicationScene( _ templateApplicationScene: CPTemplateApplicationScene, didDisconnectInterfaceController interfaceController: CPInterfaceController ) { self.interfaceController = nil } private func downloadImageAndSetupTemplates() { let urlString = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRcYUjd1FYkF04-8Vb7PKI1mGoF2quLPHKjvnR7V4ReZR8UjW-0NJ_kC7q13eISZGoTCLHaDPVbOthhH9QNq-YA0uuSUjfAoB3PPs1aXQ&s=10" guard let url = URL(string: urlString) else { setupTemplates(with: UIImage(systemName: "photo")!) return } URLSession.shared.dataTask(with: url) { [weak self] data, _, _ in let image: UIImage if let data = data, let downloaded = UIImage(data: data) { image = downloaded } else { image = UIImage(systemName: "photo")! } DispatchQueue.main.async { self?.setupTemplates(with: image) } }.resume() } private func setupTemplates(with image: UIImage) { // Tab 1 : un seul CPListImageRowItem avec 12 CPListImageRowItemRowElement let elements: [CPListImageRowItemRowElement] = (1...12).map { index in CPListImageRowItemRowElement(image: image, title: "test \(index)", subtitle: nil) } let rowItem = CPListImageRowItem(text: "Images", elements: elements, allowsMultipleLines: true) rowItem.listImageRowHandler = { item, elementIndex, completion in print("tapped element \(elementIndex)") completion() } let tab1Section = CPListSection(items: [rowItem]) let tab1Template = CPListTemplate(title: "CPListImageRowItemRowElement", sections: [tab1Section]) // Tab 2 : 12 CPListItem simples let tab2Items: [CPListItem] = (1...12).map { index in let item = CPListItem(text: "Item \(index)", detailText: "Detail \(index)") item.handler = { _, completion in print("handler Tab 2") completion() } return item } let tab2Section = CPListSection(items: tab2Items) let tab2Template = CPListTemplate(title: "CPListItem", sections: [tab2Section]) // CPTabBarTemplate avec les deux tabs let tabBar = CPTabBarTemplate(templates: [tab1Template, tab2Template]) interfaceController?.setRootTemplate(tabBar, animated: true) } } Here is a quick video:
Replies
8
Boosts
1
Views
1k
Activity
1d
About wallpaper app for iPhone Duo
I'm building a wallpaper app for iPhone Duo. The outer display is portrait (1398×2034), and the unfolded inner display is landscape (2670×1878). My wallpapers are portrait images — for example, a person centered in the frame. When the user unfolds the device and the screen changes from portrait to landscape, how does iOS adapt the wallpaper? Specifically: Does it crop a landscape region from the portrait image (which could cut off the subject)? Does it preserve the focal point the user chose when setting the wallpaper, keeping the subject in frame? Or can separate images be assigned to the outer and inner displays? I need to understand this behavior to decide what compositions to offer in my app.
Topic: UI Frameworks SubTopic: SwiftUI
Replies
1
Boosts
0
Views
52
Activity
1d
Modal on trailing
Hi I want to open a modal sheet so it's centered when the iPhone Duo is opened, but on the right side of the screen (trailing) when it's half-closed. But it seems like the "placement" property of the sheetPresentationController applies in all configurations. Is there a way to set a placement "order" (centered if possible, then trailing, then leading) ?
Topic: UI Frameworks SubTopic: UIKit
Replies
2
Boosts
0
Views
103
Activity
1d
Do GeometryReader and containerRelativeFrame Need to Be Replaced for iPhone Duo Support?
Is it necessary to replace GeometryReader and containerRelativeFrame in preparation for iPhone Duo support? If so, could you let me know the best way to do it.
Topic: UI Frameworks SubTopic: SwiftUI
Replies
2
Boosts
0
Views
75
Activity
1d