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

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
66
4d
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
193
4d
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
204
4d
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
110
4d
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
61
5d
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
5d
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
71
5d
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
122
5d
App Exposé swipe and Control–Down differ for accessory apps on macOS 27
On macOS 27.0 (26A428), Apple silicon, a physical four-finger App Exposé swipe does not expose my active AppKit accessory application's windows, including its Settings window. Control–Down does. Filed as FB24919003. I narrowed the behavior down with a two-window AppKit probe and a main menu. In an automated comparison using the same synthetic system gesture sequence each time, .accessory selected the previously active regular application's windows, .regular selected the probe's windows, and switching back to .accessory restored the mismatch. A separately generated Control–Down selected the accessory probe correctly. I activated the other regular app and then reactivated the probe before each comparison. The probe comparison did not test physical finger recognition. The macOS release that introduced this behavior is unconfirmed. The sample below uses only public AppKit APIs and is simplified from the tested probe; it compiles but has not yet been live-tested. It has no gesture recognizers, event taps, global shortcuts, custom window subclasses, or AltTab implementation. Steps for a physical-trackpad comparison: Enable the four-finger downward App Exposé gesture and Control–Down for Application windows in System Settings. Launch the sample in accessory mode and leave both windows open. Click another regular app's window, then click the sample's first window. Swipe down. Record which app's windows appear, then press Escape. Repeat the other-app → sample activation sequence, press Control–Down, record the result, then press Escape. Choose Use regular mode, repeat the activation sequence, and test again. Choose Use accessory mode, repeat the activation sequence, and test again. Start each invocation with App Exposé closed. Reactivation after each mode change matters for the comparison. Apple's window-management guide presents the swipe and Control–Down as ways to show the current app's windows. Is there a supported configuration that makes an accessory app participate in the gesture path while preserving .accessory and avoiding a Dock icon? Has anyone compared this on macOS 26 and 27? The Feedback report contains the exact tested probe as well as this simplified source. Here is the complete simplified sample, using only public AppKit APIs. Save it as AccessoryExposeSample.swift: import Cocoa final class AppDelegate: NSObject, NSApplicationDelegate { private var windows = [NSWindow]() private let modeLabel = NSTextField(labelWithString: "Activation policy: accessory") func applicationDidFinishLaunching(_ notification: Notification) { installMenu() for index in 0..<2 { addWindow(index) } windows[0].makeKeyAndOrderFront(nil) NSApp.activate(ignoringOtherApps: true) } private func installMenu() { let menu = NSMenu() let item = NSMenuItem() let submenu = NSMenu(title: "AccessoryExposeSample") submenu.addItem(withTitle: "Quit AccessoryExposeSample", action: #selector(NSApplication.terminate(_:)), keyEquivalent: "q") item.submenu = submenu menu.addItem(item) NSApp.mainMenu = menu } private func addWindow(_ index: Int) { let window = NSWindow(contentRect: NSRect(x: 100 + index * 480, y: 240, width: 460, height: 280), styleMask: [.titled, .closable, .miniaturizable], backing: .buffered, defer: false) window.title = "Accessory Exposé Sample \(index + 1)" window.isReleasedWhenClosed = false let stack = NSStackView() stack.orientation = .vertical stack.spacing = 16 stack.frame = NSRect(x: 20, y: 20, width: 420, height: 240) if index == 0 { stack.addArrangedSubview(modeLabel) stack.addArrangedSubview(NSButton(title: "Use accessory mode", target: self, action: #selector(useAccessoryMode))) stack.addArrangedSubview(NSButton(title: "Use regular mode", target: self, action: #selector(useRegularMode))) } else { stack.addArrangedSubview(NSTextField(labelWithString: "Second ordinary titled window")) } let reminder = NSTextField(wrappingLabelWithString: "Before each test, click another regular app, then click this window. After changing modes, repeat that activation sequence. Compare a downward App Exposé swipe with Control–Down.") reminder.preferredMaxLayoutWidth = 400 stack.addArrangedSubview(reminder) window.contentView?.addSubview(stack) windows.append(window) window.orderFront(nil) } @objc private func useAccessoryMode() { setPolicy(.accessory) } @objc private func useRegularMode() { setPolicy(.regular) } private func setPolicy(_ policy: NSApplication.ActivationPolicy) { guard NSApp.setActivationPolicy(policy) else { modeLabel.stringValue = "Activation policy change failed" return } modeLabel.stringValue = policy == .accessory ? "Activation policy: accessory" : "Activation policy: regular" windows[0].makeKeyAndOrderFront(nil) NSApp.activate(ignoringOtherApps: true) } } let application = NSApplication.shared application.setActivationPolicy(.accessory) let delegate = AppDelegate() application.delegate = delegate application.run() To build a standalone app bundle with a matching Swift compiler and macOS SDK selected: mkdir -p AccessoryExposeSample.app/Contents/MacOS "$(xcrun --find swiftc)" -swift-version 5 -sdk "$(xcrun --sdk macosx --show-sdk-path)" AccessoryExposeSample.swift -o AccessoryExposeSample.app/Contents/MacOS/AccessoryExposeSample cat > AccessoryExposeSample.app/Contents/Info.plist <<'PLIST' <?xml version="1.0" encoding="UTF-8"?> <plist version="1.0"><dict> <key>CFBundleIdentifier</key><string>local.apple-feedback.accessory-expose-sample</string> <key>CFBundleExecutable</key><string>AccessoryExposeSample</string> <key>CFBundleName</key><string>AccessoryExposeSample</string> <key>CFBundlePackageType</key><string>APPL</string> <key>LSUIElement</key><true/> </dict></plist> PLIST open AccessoryExposeSample.app
0
0
47
5d
Equivalent of coalescedTouchesForTouch in AppKit?
This method on UIEvent gets you more touch positions, and I think it's useful for a drawing app, to respond with greater precision to the position of the Pencil stylus. Is there a similar thing in macOS, for mouse or tablet events? I found this property mouseCoalescingEnabled, but the docs there don't describe how to get the extra events.
Topic: UI Frameworks SubTopic: AppKit Tags:
3
1
513
5d
Stale blur glass effect appears at top of UITableView and WKWebView after user updates device to iOS 27, app built with Xcode 26.3
Environment App built with Xcode 26.3 (iOS 26 SDK) Deployment Target: iOS 16+ Issue occurs only on devices upgraded to iOS 27. Works perfectly on iOS 26.x. Problem description: After end‑user upgrades their iPhone to iOS 27, a persistent stale frosted‑glass / blur rendering effect appears at the top area of screens. This symptom occurs both on native UITableView and inside WKWebView. No blur‑related code (UIVisualEffectView / backdrop‑filter) is added by our application. Layout frames, insets and contentOffset are all correct. Reproduction hints: The issue can be triggered after presenting then dismissing a WKWebView which loads H5 with overlay popup. Rendering state seems to leak to the whole app process. The leftover blur remains until push/pop the view controller. Is this an iOS 27 system bug, or do we need special adaptation for existing apps built with older Xcode 26.3 SDK? What is the proper workaround for apps compiled with Xcode26.3, since liquidGlassEffectEnabled is only available in iOS27 SDK and cannot be accessed in our current build environment.
5
0
429
5d
UICollectionView cells inside a UITableViewCell don't resize when folding/unfolding iPhone Duo
We have a UITableView where each row is a custom UITableViewCell embedding its own horizontally-paging UICollectionView (a "card" carousel — think 3 cards visible per row, one page at a time). Sizing is done the standard way via UICollectionViewDelegateFlowLayout: func collectionView(_ collectionView: UICollectionView, layout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: collectionView.frame.width, height: 213) } Symptom: On the iPhone Duo simulator, when the device is closed (cover screen, compact width), the row correctly shows the card sized to the screen. When we unfold it (inner display, regular width), the table row itself resizes to the new, much wider screen — but the card inside the embedded collection view stays stuck at its old (closed-state) width, leaving a large empty gap in the row. Folding back closed shows the same problem in reverse: the card stays sized for the wide screen and now overflows/clips. This does not happen on a normal iPhone/iPad rotation — UICollectionViewFlowLayout picks up the new width fine there. It only reproduces across the fold/unfold transition specificall
Topic: UI Frameworks SubTopic: UIKit
0
0
34
5d
How to limit SwiftUI PasteButton for custom URLs?
For GNU Taler, we defined a custom URL scheme: "taler://". We want to have a SwiftUI PasteButton in our app which is only active/enabled when the user copied a talerURI, but not for other URIs (such as https:// or mailto://). Currently we use PasteButton(supportedContentTypes: [.url]) { providers in which works, but is also enabled when the copied text is some other URI, not only for "taler://". Can we define a UTType ".taler" for PasteButton to check whether the pasteBoard has indeed a talerURI? How?
Topic: UI Frameworks SubTopic: SwiftUI
2
0
443
5d
Custom UIPresentationController cannot match iPhone Duo sheet vertical-bar behavior
Tested on iPhone Duo with iOS 27.1 in Xcode 27.1 Beta Presented VC returns .disabled from preferredVerticalBarBehavior. With UISheetPresentationController, the sheet's trailing safe-area inset is removed at all detents (including default medium and large, plus custom detents at various fixed heights). The interesting part: the status bar remains in the vertical bar for detents below UISheetPresentationControllerDetentResolutionContext.maximumDetentValue, but at detents that are greater than or equal to that maximumDetentValue, the status bar moves to the top. With a custom UIPresentationController: Default shouldPresentInFullscreen == true: trailing inset remains, regardless of presented VC's preferredVerticalBarBehavior (possibly expected) With shouldPresentInFullscreen == false: trailing inset is removed, but the status bar moves to the top regardless of the presented view's height. Using automatic as preferredVerticalBarBehavior keeps the status bar on the right, but also keeps the safe-area insets increased. Is UISheetPresentationController applying detent-aware, presentation-scoped vertical bar behavior? Is there a public way for a custom UIPresentationController to remove the sheet's vertical-bar inset while keeping the status bar vertical [until the presentation reaches full height]?
0
0
77
5d
UITabBarController becomes a sidebar on the inner display
With the default mode of .automatic, the inner display shows a sidebar instead of a bottom tab bar. The sidebar draws UIKit’s dimming view over the selected view controller, which hides our map. We force mode = .tabBar on iOS 18. Is a bottom tab bar on the Duo inner display supported, or is the sidebar the intended phone-unfolded layout?
Topic: UI Frameworks SubTopic: UIKit
1
0
389
5d
Tab item titles stay truncated after the bar width changes
UITabBar measures titles on the first layout pass. After unfolding, the bar is much wider but labels stay truncated with an ellipsis until the user switches tabs. Reapplying standardAppearance does not rebuild the buttons. Is there a public API to invalidate tab-item title measurement when the bar’s width changes?
Topic: UI Frameworks SubTopic: UIKit
1
0
336
5d
Guidance on UITabBarController sidebar suppression for foldable iPhone regular-width layouts
On unfolding, our app's horizontalSizeClass becomes .regular, and UITabBarController automatically promotes to the iPadOS-style sidebar. We suppress this with mode = .tabBar (iOS 18+) and sidebar.preferredPlacement = .tabBar / sidebar.preferredLayout = .tile (iOS 27+) to keep a bottom tab bar. Is this the correct/recommended approach for a foldable iPhone's inner display, or is there a foldable-specific tab bar mode we should be using instead?
Topic: UI Frameworks SubTopic: UIKit
1
1
363
5d
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
66
Activity
4d
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
193
Activity
4d
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
204
Activity
4d
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
110
Activity
4d
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
61
Activity
5d
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
5d
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
71
Activity
5d
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
122
Activity
5d
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
108
Activity
5d
App Exposé swipe and Control–Down differ for accessory apps on macOS 27
On macOS 27.0 (26A428), Apple silicon, a physical four-finger App Exposé swipe does not expose my active AppKit accessory application's windows, including its Settings window. Control–Down does. Filed as FB24919003. I narrowed the behavior down with a two-window AppKit probe and a main menu. In an automated comparison using the same synthetic system gesture sequence each time, .accessory selected the previously active regular application's windows, .regular selected the probe's windows, and switching back to .accessory restored the mismatch. A separately generated Control–Down selected the accessory probe correctly. I activated the other regular app and then reactivated the probe before each comparison. The probe comparison did not test physical finger recognition. The macOS release that introduced this behavior is unconfirmed. The sample below uses only public AppKit APIs and is simplified from the tested probe; it compiles but has not yet been live-tested. It has no gesture recognizers, event taps, global shortcuts, custom window subclasses, or AltTab implementation. Steps for a physical-trackpad comparison: Enable the four-finger downward App Exposé gesture and Control–Down for Application windows in System Settings. Launch the sample in accessory mode and leave both windows open. Click another regular app's window, then click the sample's first window. Swipe down. Record which app's windows appear, then press Escape. Repeat the other-app → sample activation sequence, press Control–Down, record the result, then press Escape. Choose Use regular mode, repeat the activation sequence, and test again. Choose Use accessory mode, repeat the activation sequence, and test again. Start each invocation with App Exposé closed. Reactivation after each mode change matters for the comparison. Apple's window-management guide presents the swipe and Control–Down as ways to show the current app's windows. Is there a supported configuration that makes an accessory app participate in the gesture path while preserving .accessory and avoiding a Dock icon? Has anyone compared this on macOS 26 and 27? The Feedback report contains the exact tested probe as well as this simplified source. Here is the complete simplified sample, using only public AppKit APIs. Save it as AccessoryExposeSample.swift: import Cocoa final class AppDelegate: NSObject, NSApplicationDelegate { private var windows = [NSWindow]() private let modeLabel = NSTextField(labelWithString: "Activation policy: accessory") func applicationDidFinishLaunching(_ notification: Notification) { installMenu() for index in 0..<2 { addWindow(index) } windows[0].makeKeyAndOrderFront(nil) NSApp.activate(ignoringOtherApps: true) } private func installMenu() { let menu = NSMenu() let item = NSMenuItem() let submenu = NSMenu(title: "AccessoryExposeSample") submenu.addItem(withTitle: "Quit AccessoryExposeSample", action: #selector(NSApplication.terminate(_:)), keyEquivalent: "q") item.submenu = submenu menu.addItem(item) NSApp.mainMenu = menu } private func addWindow(_ index: Int) { let window = NSWindow(contentRect: NSRect(x: 100 + index * 480, y: 240, width: 460, height: 280), styleMask: [.titled, .closable, .miniaturizable], backing: .buffered, defer: false) window.title = "Accessory Exposé Sample \(index + 1)" window.isReleasedWhenClosed = false let stack = NSStackView() stack.orientation = .vertical stack.spacing = 16 stack.frame = NSRect(x: 20, y: 20, width: 420, height: 240) if index == 0 { stack.addArrangedSubview(modeLabel) stack.addArrangedSubview(NSButton(title: "Use accessory mode", target: self, action: #selector(useAccessoryMode))) stack.addArrangedSubview(NSButton(title: "Use regular mode", target: self, action: #selector(useRegularMode))) } else { stack.addArrangedSubview(NSTextField(labelWithString: "Second ordinary titled window")) } let reminder = NSTextField(wrappingLabelWithString: "Before each test, click another regular app, then click this window. After changing modes, repeat that activation sequence. Compare a downward App Exposé swipe with Control–Down.") reminder.preferredMaxLayoutWidth = 400 stack.addArrangedSubview(reminder) window.contentView?.addSubview(stack) windows.append(window) window.orderFront(nil) } @objc private func useAccessoryMode() { setPolicy(.accessory) } @objc private func useRegularMode() { setPolicy(.regular) } private func setPolicy(_ policy: NSApplication.ActivationPolicy) { guard NSApp.setActivationPolicy(policy) else { modeLabel.stringValue = "Activation policy change failed" return } modeLabel.stringValue = policy == .accessory ? "Activation policy: accessory" : "Activation policy: regular" windows[0].makeKeyAndOrderFront(nil) NSApp.activate(ignoringOtherApps: true) } } let application = NSApplication.shared application.setActivationPolicy(.accessory) let delegate = AppDelegate() application.delegate = delegate application.run() To build a standalone app bundle with a matching Swift compiler and macOS SDK selected: mkdir -p AccessoryExposeSample.app/Contents/MacOS "$(xcrun --find swiftc)" -swift-version 5 -sdk "$(xcrun --sdk macosx --show-sdk-path)" AccessoryExposeSample.swift -o AccessoryExposeSample.app/Contents/MacOS/AccessoryExposeSample cat > AccessoryExposeSample.app/Contents/Info.plist <<'PLIST' <?xml version="1.0" encoding="UTF-8"?> <plist version="1.0"><dict> <key>CFBundleIdentifier</key><string>local.apple-feedback.accessory-expose-sample</string> <key>CFBundleExecutable</key><string>AccessoryExposeSample</string> <key>CFBundleName</key><string>AccessoryExposeSample</string> <key>CFBundlePackageType</key><string>APPL</string> <key>LSUIElement</key><true/> </dict></plist> PLIST open AccessoryExposeSample.app
Replies
0
Boosts
0
Views
47
Activity
5d
Equivalent of coalescedTouchesForTouch in AppKit?
This method on UIEvent gets you more touch positions, and I think it's useful for a drawing app, to respond with greater precision to the position of the Pencil stylus. Is there a similar thing in macOS, for mouse or tablet events? I found this property mouseCoalescingEnabled, but the docs there don't describe how to get the extra events.
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
3
Boosts
1
Views
513
Activity
5d
Stale blur glass effect appears at top of UITableView and WKWebView after user updates device to iOS 27, app built with Xcode 26.3
Environment App built with Xcode 26.3 (iOS 26 SDK) Deployment Target: iOS 16+ Issue occurs only on devices upgraded to iOS 27. Works perfectly on iOS 26.x. Problem description: After end‑user upgrades their iPhone to iOS 27, a persistent stale frosted‑glass / blur rendering effect appears at the top area of screens. This symptom occurs both on native UITableView and inside WKWebView. No blur‑related code (UIVisualEffectView / backdrop‑filter) is added by our application. Layout frames, insets and contentOffset are all correct. Reproduction hints: The issue can be triggered after presenting then dismissing a WKWebView which loads H5 with overlay popup. Rendering state seems to leak to the whole app process. The leftover blur remains until push/pop the view controller. Is this an iOS 27 system bug, or do we need special adaptation for existing apps built with older Xcode 26.3 SDK? What is the proper workaround for apps compiled with Xcode26.3, since liquidGlassEffectEnabled is only available in iOS27 SDK and cannot be accessed in our current build environment.
Replies
5
Boosts
0
Views
429
Activity
5d
Refresh UI behaviour function for iPhone Duo
is there any particular function (same as viewDidLayoutSubviews) which call when I'm opening duo on when my open app doing the task?
Topic: UI Frameworks SubTopic: UIKit
Replies
0
Boosts
0
Views
33
Activity
5d
NSCollectionLayoutDecorationItem background cannot extend into vertical toolbar on iPhone Duo
A NSCollectionLayoutSection can have background decorations, set through the decorationItems property. Currently these decorations will never overlap the horizontal safe area on iPhone Duo, causing my backgrounds to stop while the horizontal scrolling items keep going. iOS 27.1 build 24A94401 SDK version 24A94403
Topic: UI Frameworks SubTopic: UIKit
Replies
0
Boosts
0
Views
36
Activity
5d
UICollectionView cells inside a UITableViewCell don't resize when folding/unfolding iPhone Duo
We have a UITableView where each row is a custom UITableViewCell embedding its own horizontally-paging UICollectionView (a "card" carousel — think 3 cards visible per row, one page at a time). Sizing is done the standard way via UICollectionViewDelegateFlowLayout: func collectionView(_ collectionView: UICollectionView, layout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: collectionView.frame.width, height: 213) } Symptom: On the iPhone Duo simulator, when the device is closed (cover screen, compact width), the row correctly shows the card sized to the screen. When we unfold it (inner display, regular width), the table row itself resizes to the new, much wider screen — but the card inside the embedded collection view stays stuck at its old (closed-state) width, leaving a large empty gap in the row. Folding back closed shows the same problem in reverse: the card stays sized for the wide screen and now overflows/clips. This does not happen on a normal iPhone/iPad rotation — UICollectionViewFlowLayout picks up the new width fine there. It only reproduces across the fold/unfold transition specificall
Topic: UI Frameworks SubTopic: UIKit
Replies
0
Boosts
0
Views
34
Activity
5d
How to limit SwiftUI PasteButton for custom URLs?
For GNU Taler, we defined a custom URL scheme: "taler://". We want to have a SwiftUI PasteButton in our app which is only active/enabled when the user copied a talerURI, but not for other URIs (such as https:// or mailto://). Currently we use PasteButton(supportedContentTypes: [.url]) { providers in which works, but is also enabled when the copied text is some other URI, not only for "taler://". Can we define a UTType ".taler" for PasteButton to check whether the pasteBoard has indeed a talerURI? How?
Topic: UI Frameworks SubTopic: SwiftUI
Replies
2
Boosts
0
Views
443
Activity
5d
Custom UIPresentationController cannot match iPhone Duo sheet vertical-bar behavior
Tested on iPhone Duo with iOS 27.1 in Xcode 27.1 Beta Presented VC returns .disabled from preferredVerticalBarBehavior. With UISheetPresentationController, the sheet's trailing safe-area inset is removed at all detents (including default medium and large, plus custom detents at various fixed heights). The interesting part: the status bar remains in the vertical bar for detents below UISheetPresentationControllerDetentResolutionContext.maximumDetentValue, but at detents that are greater than or equal to that maximumDetentValue, the status bar moves to the top. With a custom UIPresentationController: Default shouldPresentInFullscreen == true: trailing inset remains, regardless of presented VC's preferredVerticalBarBehavior (possibly expected) With shouldPresentInFullscreen == false: trailing inset is removed, but the status bar moves to the top regardless of the presented view's height. Using automatic as preferredVerticalBarBehavior keeps the status bar on the right, but also keeps the safe-area insets increased. Is UISheetPresentationController applying detent-aware, presentation-scoped vertical bar behavior? Is there a public way for a custom UIPresentationController to remove the sheet's vertical-bar inset while keeping the status bar vertical [until the presentation reaches full height]?
Replies
0
Boosts
0
Views
77
Activity
5d
UITabBarController becomes a sidebar on the inner display
With the default mode of .automatic, the inner display shows a sidebar instead of a bottom tab bar. The sidebar draws UIKit’s dimming view over the selected view controller, which hides our map. We force mode = .tabBar on iOS 18. Is a bottom tab bar on the Duo inner display supported, or is the sidebar the intended phone-unfolded layout?
Topic: UI Frameworks SubTopic: UIKit
Replies
1
Boosts
0
Views
389
Activity
5d
Tab item titles stay truncated after the bar width changes
UITabBar measures titles on the first layout pass. After unfolding, the bar is much wider but labels stay truncated with an ellipsis until the user switches tabs. Reapplying standardAppearance does not rebuild the buttons. Is there a public API to invalidate tab-item title measurement when the bar’s width changes?
Topic: UI Frameworks SubTopic: UIKit
Replies
1
Boosts
0
Views
336
Activity
5d
Guidance on UITabBarController sidebar suppression for foldable iPhone regular-width layouts
On unfolding, our app's horizontalSizeClass becomes .regular, and UITabBarController automatically promotes to the iPadOS-style sidebar. We suppress this with mode = .tabBar (iOS 18+) and sidebar.preferredPlacement = .tabBar / sidebar.preferredLayout = .tile (iOS 27+) to keep a bottom tab bar. Is this the correct/recommended approach for a foldable iPhone's inner display, or is there a foldable-specific tab bar mode we should be using instead?
Topic: UI Frameworks SubTopic: UIKit
Replies
1
Boosts
1
Views
363
Activity
5d