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
6.5k
Sep ’26
Age Range Functionality in MacOS 27.2 no handle?
I have a running implementation for an iOS Application which is using AgeRange. It was running very well on Mac OS below 27 and was getting the results. It is still working on iOS 27.2 but now in MacOS 27.2 with the same code base I'm getting an } catch AgeRangeService.Error.notAvailable { NSLog("[AgeRangeDeclaration] Handle not available error")Is there a change for MacOS 27 which has to be implemented or do I have to configure something else?
Topic: UI Frameworks SubTopic: General
0
0
38
5h
Fundamental error in PDFOutline created syntax
PDFKit's PDFOutline creates fundamentally flawed PDF syntax when it creates outlines ("Bookmarks") in a PDF document. A PDF document is created with three outlines: "Page 1", "Page 2" and "Page 3". Each is a child of the former, so "Page 3" is a child of "Page 2", and "Page 2" is a child of "Page 1". PDFKit produces flawed PDF syntax, with duplicate entries for each bookmark, missing sibling links, and a convoluted Parent > Child relationship. 3 0 obj << /Type /Pages /Parent 45 0 R /Count 8 /Kids [ 2 0 R 6 0 R 9 0 R 12 0 R 15 0 R 18 0 R 21 0 R 24 0 R ] >> endobj 28 0 obj << /Type /Pages /Parent 45 0 R /Count 3 /Kids [ 27 0 R 31 0 R 34 0 R ] >> endobj 45 0 obj << /Type /Pages /MediaBox [0 0 612 792] /Count 11 /Kids [ 3 0 R 28 0 R ] >> endobj 46 0 obj << /Type /Catalog /Outlines 1 0 R /Pages 45 0 R >> endobj 1 0 obj << /First 47 0 R /Last 48 0 R >> endobj 48 0 obj << /Last 49 0 R /Count -1 /First 50 0 R /Title (Page 1) /Dest [ 2 0 R /XYZ 0 841.88 null ] /Parent 51 0 R >> endobj 51 0 obj << >> endobj 50 0 obj << /Last 52 0 R /Count -1 /First 53 0 R /Title (Page 2) /Dest [ 6 0 R /XYZ 0 841.88 null ] /Parent 51 0 R >> endobj 53 0 obj << /Dest [ 9 0 R /XYZ 0 841.88 null ] /Count 0 /Title (Page 3) /Parent 51 0 R >> endobj 52 0 obj << /Dest [ 9 0 R /XYZ 0 841.88 null ] /Count 0 /Title (Page 3) /Parent 51 0 R >> endobj 49 0 obj << /Last 52 0 R /Count -1 /First 53 0 R /Title (Page 2) /Dest [ 6 0 R /XYZ 0 841.88 null ] /Parent 51 0 R >> endobj 47 0 obj << /Last 49 0 R /Count -1 /First 50 0 R /Title (Page 1) /Dest [ 2 0 R /XYZ 0 841.88 null ] /Parent 51 0 R >> endobj(The Parent of all the outline objects is given as object 51, which is blank. The First/Last objects don't link correctly to the expected hierarchy, etc, etc.) Acrobat preflight will flag this as a syntax error, though the bookmarks do largely function in most viewers. Preview doesn't show the top-level outline, though that might relate to FB4013726, filed in 2018. I have shown the created syntax to ChatGPT, which also confirmed that the syntax does not conform to the expected PDF spec: This isn’t simply a matter of PDFKit choosing an unnecessarily elaborate but valid representation. There are genuine structural problems: The top-level Page 1 object’s /Parent does not point to the /Outlines dictionary. The child objects’ /Parent does not point to their actual containing outline. There are duplicate outline objects for Page 1, Page 2 and Page 3. The required sibling Prev/Next chains are absent. The /First//Last relationships don’t correspond cleanly to the claimed hierarchy. The errors are entirely reproducible in any PDFOutlines created by PDFKit. I have filed this as FB25328043. ... and in 2021 as FB8960602. ... and in 2019 as FB5313583.
Topic: UI Frameworks SubTopic: AppKit Tags:
2
0
334
13h
NSScrollView: Overriding "scrollWheel(with:)" can cause a never-ending live scroll
Overview I'm developing an app that depends on NSScrollView to implement a scrollable and zoomable canvas. I need to override NSScrollView.scrollWheel(with:) to implement Option-zooming (holding Option while scrolling up/down to zoom in/out). I've found that simply adding these three lines of code in my NSScrollView subclass: override func scrollWheel(with event: NSEvent) { super.scrollWheel(with: event) }is enough to cause a live scroll to never end, and NSScrollView.didEndLiveScrollNotification to never fire. My app depends on that notification firing so that it can disable some interactions during a live scroll. Furthermore, while the NSScrollView is "stuck" in the live scroll, it's not possible to perform a live magnify. There are also some other effects, including elevated CPU usage and persistent scroll indicators. The issue is occurring with Xcode 27.1 (27A9275) and macOS 27.2 (26B123). I have modified the macOS App project template to showcase the issue. The sample project, along with a screen recording of the issue, can be downloaded from here: https://drive.google.com/drive/folders/1F5sF2NA230NkGbQdLfbV6vM1XmfY1-uT?usp=sharing I hope that Apple can fix this issue soon, as it's a frustrating user experience when the canvas gets stuck while scrolling. I've already filed this in Feedback Assistant under FB25362729. Steps to Reproduce To recreate the issue, follow these steps: Download and extract the "Xcode Project.zip" file from the link above. Open the extracted "NSScrollViewTest" project in Xcode. Build and run the "NSScrollViewTest" app. Scroll all the way to the right edge of the gray canvas using the horizontal scroll gesture on Magic Trackpad. If you comment out lines 8–10 of ScrollView.swift, the issue goes away. The "Issue Recording.mov" file from the link above provides a detailed video of how to recreate the issue.
Topic: UI Frameworks SubTopic: AppKit
9
0
596
15h
iOS 27 regression - minimized search item in top toolbar breaks its state
struct ContentView: View { @State var searchText: String = "" var body: some View { TabView { Tab { NavigationStack { List { Text("Hello!") Text("Hello!") Text("Hello!") Text("Hello!") Text("Hello!") Text("Hello!") } .navigationTitle("Have a title") .searchable(text: $searchText, placement: .toolbar) .searchToolbarBehavior(.minimize) .toolbar { DefaultToolbarItem(kind: .search, placement: .topBarTrailing) } } } } } } In iOS 26, this worked no problem. In iOS 27, this leaves the search bar either unable to collapse (when pressing the close button) or in a broken state where it cannot be opened again.
Topic: UI Frameworks SubTopic: SwiftUI
8
11
1.7k
15h
Workaround for NSTableView bugs introduced in macOS 27
MacOS 27 (or perhaps 26, I never used it) introduces two bugs in NSTableView (and delegate). It's always a pleasure when you find that your app no longer works properly. First, when the delegate responds to tableView:pasteboardWriterForRow:, no row can be selected by click & drag (even if the method returns nil). Which mean that clicking and dragging the mouse on rows that are not draggable simply does nothing (no selection), which is a frustrating user experience, especially considering that the same action selects rows on macOS 15. The second bug is that tableView.verticalMotionCanBeginDrag = NO is simply ignored. It doesn’t work. So, a click followed by an immediate vertical drag drags the clicked row instead of selecting rows if tableView:pasteboardWriterForRow: does not return nil. Again, it did select rows on macOS 15. That's what verticalMotionCanBeginDrag = NO is for. To work around the first bug, I implement respondsToSelector: in the delegate to return NO when the selector is tableView:pasteboardWriterForRow: and the clicked row is not draggable. This solution is not elegant, as theclickedRow property of the tableview always returns -1 when the method is called. Which means I need to determine the clicked row by other means (using the mouse location and stuff). (This solution should in principle allow working around the second bug, but I haven’t implemented it yet. It would require determining the delay between the click and the drag and the direction of the drag). So my question is: does anyone see a better workaround for these bugs?
Topic: UI Frameworks SubTopic: AppKit
3
0
186
16h
NavigationSplitView Binding to NavigationSplitViewColumn reset with every NavigationStack path change
I try to create a Navigation that works on iPhone, iPhone Duo and iPad. NavigationSplitView collapses for compact form factors and makes iPhone Duo support much simpler. The Problem is the semantic of the collapse. Switch from detail to sidebar on compact is not a 'back' action in my case. It should have my choosen Icon and has a meaning. So i wanted to control this using the NavigationSpliViewColumn Binding. This does work forward and backward as long as no NavigationStack was used before. But it stops working when you return to the detail root from a Navigation-Action. I left the Backbutton visible so you can test, that it continues to work, when no Navigation-Action preceeded the switch. Here is my Code: import SwiftUI @Observable final class Compass { var path: [Route] init() { self.path = [] } } enum Route: Hashable { case goal } struct ContentView: View { @Environment(\.horizontalSizeClass) private var hsize @State private var compass: Compass = Compass() @State var column: NavigationSplitViewColumn = .detail var body: some View { NavigationSplitView(preferredCompactColumn: $column) { OverviewScreen(column: $column) } detail: { TodayScreen() .toolbar { ToolbarItem(placement: .topBarLeading) { Button("overview", systemImage: "calendar") { self.column = .sidebar } } } } .environment(compass) .onChange(of: column) { old, new in print("column:", old, "→", new) } } } struct OverviewScreen: View { @Binding var column: NavigationSplitViewColumn @Environment(Compass.self) var compass var body: some View { @Bindable var compass = self.compass ScrollView { Text("Overview") .font(.largeTitle) .fontWeight(.heavy) Button("Switch") { self.column = .detail } } } } struct TodayScreen: View { @Environment(Compass.self) var compass var body: some View { @Bindable var compass = self.compass NavigationStack(path: $compass.path) { ScrollView { Text("Today") .font(.largeTitle) .fontWeight(.heavy) Button("Goals programtically", systemImage: "flag.fill") { self.compass.path = [.goal] } NavigationLink(value: Route.goal) { Label("Goal Link", systemImage: "flag.fill") } } .navigationDestination(for: Route.self, destination: self.screen) } } @ContentBuilder func screen(for route: Route) -> some View { switch route { case .goal: Text("Goals") } } } #Preview { ContentView() }This seems unexpected behaviour. If you ask AI the mental model is NavigationSplitViewColumn represents which column is currently visible for the user. That model would be wrong. Also i can't understand why a NavigationStack has to change the Binding? What am i missing here? Is my idea of the programmatic switch not supported? There are other ways to push from compact to your detail column again, but they all have trade-offs or run into other problems. I would appreciate any help here. AI has not understood this and only does surface level work arounds that fix nothing.
0
0
22
1d
Keyboard Toolbar Padding iOS26
When I create a SwiftUI toolbar item with placement of .keyboard on iOS 26, the item appears directly on top of and in contact with the keyboard. This does not look good visually nor does it match the behavior seen in Apple's apps, such as Reminders. Adding padding to the contents of the toolbar item only expands the size of the item but does not separate the capsule background of the item from the keyboard. How can I add vertical padding or spacing to separate the toolbar item capsule from the keyboard?
Topic: UI Frameworks SubTopic: SwiftUI
12
9
2.1k
1d
UITableView row reordering no longer works under macOS 27 with Mac Catalyst
Under macOS 27 using Mac Catalyst for a UIKit-based app, If you present a view controller with a table view as a form sheet or page sheet, row reordering fails to function. You can drag a row as expected but the blue movement bar never appears and if you drop the row it simply returns to its original location. The exact same view controller presented as a popover works just fine. The exact same view controller not presented as a modal (such as the app's root controller) works just fine. This is a serious bug affecting existing applications and being reported by paying customers. This has been reported as FB25038883 which includes a simple sample app demonstrating the issue.
2
0
413
1d
NSSegmentedControl style ineffective.
I'm not sure if it's something wrong with my XCode install (Version 27.1, macOS 27.2) or what, because such a serious issue should be mentioned already... Basically, building my objC app with the latest XCode makes the NSSegmentedControl style ineffective. Likewise, changing the style in the attribute of the control in interface builder has no visible effect on the preview either. Changing the style in code or in IB has no effect. The control appears stuck with a style that implements a blue background for the selected segment (some default style I guess). I tried with a minimalistic app that includes only one window and the control. The issue is still present. Any suggestion? Am I the only one experiencing this?
Topic: UI Frameworks SubTopic: AppKit
8
0
464
1d
Clipped render of dragged NSTableView row on macOS 27.
On macOS 27, dragged rows on my app's table views are excessively clipped (see image). I don't override methods like `tableView:draggingSession:willBeginAtPoint:forRowIndexes:` so I don’t supply my own drag images, and I don’t use NSTableView suclasses. I tried on a toy project containg with a single table view in a window, and it did not reproduce this behavior. I wonder if my issue if it’s due to my app’s table views being embedded in split views or something. Anyway, how can I fix that?
Topic: UI Frameworks SubTopic: AppKit
0
0
171
1d
NSScrollView scrolling hitch
When scrolling a basic NSScrollView there seems to be a sudden jump after each flick. Scrolling does not appear smooth and is disorientating. A scroll jump seems to happen directly after letting go of a scroll flick using a trackpad/mouse. Right at that moment the scroll turns into a momentum scroll, slowly decreasing the speed. But the first frame after the gesture the content jumps forward, more than what is expected. Observations: Counterintuitively, scrolling appears to be smoother when disabling NSScrollView.isCompatibleWithResponsiveScrolling. If disabled using a custom NSScrollView subclass there is no large jump anymore. Scrolling also appears to be smoother using a SwiftUI ScrollView. I assume that has the same behaviour as a disabled isCompatibleWithResponsiveScrolling Ironically a WKWebView scrolls much smoother. No sudden jump is observable. It also seems to scroll with faster acceleration, but the individual frames do appear smoother. Why is this better than a native NSScrollView? Elastic scrolling at the bounds of the scroll view also appears much smoother for WKWebViews. When pulling to refresh there is a jump for NSScrollView/SwiftUI, but not for WKWebView. When using an NSScrollView with isCompatibleWithResponsiveScrolling disabled, scrolling appears just as smooth as WKWebView on macOS 13 Ventura and below. On macOS 14 Sonoma scrolling behaviour is suddenly different. Please see a sample project with 4 different scroll views side by side: https://github.com/floorish/ScrollTest Screen recordings show the sudden jumps when scrolling and when elastic scrolling. Tested on Intel & Arm Macs, macOS 11 Big Sur through 15 Sequoia, built with Xcode 16. Should isCompatibleWithResponsiveScrolling be disabled on Sonoma+? Are there any drawbacks? There is also no overdraw anymore since Monterey, as described in https://developer.apple.com/library/archive/releasenotes/AppKit/RN-AppKitOlderNotes/#10_9Scrolling Even with responsive scrolling disabled, why is WKWebView scrolling much smoother than NSScrollView?
Topic: UI Frameworks SubTopic: AppKit Tags:
9
3
1.4k
1d
What pattern to use for an iPhone Tabview app
I have an iPhone tab view application that has not been designed for iPad, and I am aiming to add a left-hand bar that summarises some content and keeps visible what is normally a sheet. What pattern would work best for this? At present, I pass the view to another view with a navigation stack containing an arrangement view with the previous view and then the sidebar as a secondary view within it—would that be the appropriate approach?
Topic: UI Frameworks SubTopic: SwiftUI
3
0
392
1d
State Restoration no longer works in a Mac Catalyst based app when run on macOS 27.x
As reported in FB25363417: A UIKit based app running on macOS 27.2 (or macOS 27.0.1) via Mac Catalyst no longer has functioning state restoration. Upon app restart, there is no NSUserActivity being provided to the scene in the UISceneDelegate method scene(_:willConnectTo:options:). This can be tested with Apple’s own sample app “Restoring your app’s state”. Just update the sample project with support for a Mac Catalyst build. Using Xcode 27.2 on a Mac with macOS 27.0 or 27.2, build and run the Mac Catalyst version of the app. The main screen appears with a list of products. Select any product so you see details of the product. Quit the app. Run the app again. Note that you are not returned to the previously selected product detail screen. Instead, you just see the main list of products. If you run the same app and perform the same steps on a Mac running macOS 26.x, then when the app is restarted, you correctly get returned to the previously selected product detail screen. The problem is being caused by no NSUserActivity being passed into the scene delegate on app startup. While running the app on a Mac with macOS 27.x, put a breakpoint on the initial guard statement in scene(_:willConnectTo:options:) and you will see there is no activity on app restart. This is impacting paid customers of my existing app since upgrading to macOS 27. They no longer get returned to the app’s previous state when restarting the app. It is expected that state restoration should work on macOS 27 just as well as it does under macOS 26 in an app built with Mac Catalyst.
0
0
75
1d
UIKIt, iOS 27, UIDocumentPickerViewController(forExporting: [fileURL])
My App saves files using the UIDocumentPickerViewController. This works from iOS 17 to 26. Usually, you have a file with a given name in your sandbox, which you can then export via the pickerVC. In the pickerVC you change the name. In iOS 27 the file name is greyed-out and you can't change it here. The file can be exported only with the pre-given name. Is this a new behaviour or bug in iOS 27?
Topic: UI Frameworks SubTopic: UIKit
0
0
83
1d
UITextContentType.cellularIMEI works on iOS 27+ only
During testing, we found that IMEI AutoFill behaves differently by iOS version, independent of the entitlement, and would like to confirm the expected behavior. Test details Implementation: textContentType = .cellularIMEI on the IMEI input field Entitlement status: no carrier-related entitlements in the test build Observed results iOS 27: The IMEI AutoFill suggestion appears and works in any app, regardless of carrier entitlement. iOS 26 and earlier: The IMEI AutoFill suggestion does not appear. Questions Is it the expected and intended behavior that, on iOS 27, IMEI AutoFill is available to any app without a carrier entitlement? On iOS versions earlier than 27 (iOS 17.4 to 26), is the public cellular plan entitlement required for IMEI AutoFill to work? If not, are there other conditions or requirements? On dual-IMEI devices, which IMEI (IMEI or IMEI2) is filled when .cellularIMEI is used on iOS 27? Should we use .cellularIMEI1 / .cellularIMEI2 to specify it explicitly? Thank you for your support.
1
0
86
2d
UIKit snapshot views render empty into UIImage on physical devices, but work in Simulator
Is there a supported way to convert the cached contents of a UIKit snapshot view into a UIImage on physical iOS/iPadOS devices? A view returned by snapshotView(afterScreenUpdates:) displays correctly on hardware, but drawing that view into a UIGraphicsImageRenderer produces no cached-content pixels. drawHierarchy(in:afterScreenUpdates:) still returns true. The same base experiment succeeds in Simulator. Feedback Assistant report: FB25336445. A standalone reproducer and measurements are attached there; use the corrected replica-readback-ios-27.0.1-fixed-project.zip attachment. Tested environments Physical iPhone 15 Pro Max: iOS 27.0.1 (24A446). Physical iPad mini (6th generation): iPadOS 26.6.1 (23G83). Two independent app launches produced identical measurements. Simulator: iPhone 18 Pro / iOS 27.0 and iPhone 15 Pro Max / iOS 26.1. The app is a standalone UIKit Release build, launched without a debugger or XCTest. It uses an ordinary red UIView and a white UILabel: no WebKit, Liquid Glass, video, secure text fields, third-party libraries, or private API calls. I have not tested a physical iPhone on the 26 series or iOS 27.0.2. The Simulator and device OS patch versions differ, so this is not a controlled OS-only comparison. Reproduction Display a red 240 x 160 UIView containing a white UILabel; allow it to render. Draw the original view into an image as a positive control. Call source.snapshotView(afterScreenUpdates: false), attach the replica to the window at the source frame, wait 500 ms, hide the original, then wait another 500 ms. Draw the attached replica into transparent and cyan-prefilled image contexts. Add an ordinary red 30 x 30 child UIView to the replica, wait 500 ms, and capture again. Repeat with replicas from UIWindow.snapshotView and UIScreen.snapshotView. This is the capture operation, called on the main actor after those waits: func rasterize(_ target: UIView, cyanBackground: Bool) -> UIImage { let format = UIGraphicsImageRendererFormat() format.scale = 1 format.opaque = false return UIGraphicsImageRenderer(size: target.bounds.size, format: format) .image { context in if cyanBackground { UIColor.cyan.setFill() context.fill(target.bounds) } let success = target.drawHierarchy( in: target.bounds, afterScreenUpdates: true ) print("drawHierarchy:", success) } }Results On both physical devices: The original 240 x 160 UIView renders normally: all 38,400 pixels are nontransparent. The replica on a transparent target produces zero nontransparent pixels. The replica on a cyan target leaves all 38,400 pixels cyan. Adding an ordinary child view produces approximately 900 red pixels, but the replica's cached contents are still missing. UIView, UIWindow and UIScreen replicas all exhibit the omission, while drawHierarchy returns true. In both tested Simulators, the base experiment renders the replica contents and overwrites the cyan background. The child-marker addition was tested on physical devices only. These counts are measured from the CGImage before PNG encoding. Thus “black output” with an opaque context appears to be missing content, not pixels painted black: transparent and cyan targets retain their original contents. Questions Is bitmap readback of these snapshot views supported on physical devices, or are they only intended for on-screen composition? If unsupported, is the Simulator behavior expected, and why does drawHierarchy return success despite omitting the visible cached contents? Is there a supported API to materialize those cached contents as an image, without starting a screen-recording session? Capturing the original view directly is a useful control, but does not answer how to read back an already-created snapshot. I found this older AVSampleBufferDisplayLayer discussion, which also describes a correctly displayed snapshot view becoming black when converted to an image. My reproducer uses only ordinary UIKit views; I do not know whether the underlying cause is related.
Topic: UI Frameworks SubTopic: UIKit
5
0
338
2d
Best way to position game touch controls around the iPhone Duo hinge
For a full-screen game with a Metal/Unreal rendering view and a SwiftUI overlay for touch controls, what is the recommended way to keep interactive controls away from the hinge while still allowing the rendered game world to use the full display? Would you recommend querying ReservedRegion in the SwiftUI overlay while allowing the underlying render view to remain edge-to-edge? Also, should control placement respond continuously while the device is being folded, or primarily respond to layout/reserved-region changes once the pose changes?
Topic: UI Frameworks SubTopic: SwiftUI
1
0
83
2d
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
6.5k
Activity
Sep ’26
Age Range Functionality in MacOS 27.2 no handle?
I have a running implementation for an iOS Application which is using AgeRange. It was running very well on Mac OS below 27 and was getting the results. It is still working on iOS 27.2 but now in MacOS 27.2 with the same code base I'm getting an } catch AgeRangeService.Error.notAvailable { NSLog("[AgeRangeDeclaration] Handle not available error")Is there a change for MacOS 27 which has to be implemented or do I have to configure something else?
Topic: UI Frameworks SubTopic: General
Replies
0
Boosts
0
Views
38
Activity
5h
Fundamental error in PDFOutline created syntax
PDFKit's PDFOutline creates fundamentally flawed PDF syntax when it creates outlines ("Bookmarks") in a PDF document. A PDF document is created with three outlines: "Page 1", "Page 2" and "Page 3". Each is a child of the former, so "Page 3" is a child of "Page 2", and "Page 2" is a child of "Page 1". PDFKit produces flawed PDF syntax, with duplicate entries for each bookmark, missing sibling links, and a convoluted Parent > Child relationship. 3 0 obj << /Type /Pages /Parent 45 0 R /Count 8 /Kids [ 2 0 R 6 0 R 9 0 R 12 0 R 15 0 R 18 0 R 21 0 R 24 0 R ] >> endobj 28 0 obj << /Type /Pages /Parent 45 0 R /Count 3 /Kids [ 27 0 R 31 0 R 34 0 R ] >> endobj 45 0 obj << /Type /Pages /MediaBox [0 0 612 792] /Count 11 /Kids [ 3 0 R 28 0 R ] >> endobj 46 0 obj << /Type /Catalog /Outlines 1 0 R /Pages 45 0 R >> endobj 1 0 obj << /First 47 0 R /Last 48 0 R >> endobj 48 0 obj << /Last 49 0 R /Count -1 /First 50 0 R /Title (Page 1) /Dest [ 2 0 R /XYZ 0 841.88 null ] /Parent 51 0 R >> endobj 51 0 obj << >> endobj 50 0 obj << /Last 52 0 R /Count -1 /First 53 0 R /Title (Page 2) /Dest [ 6 0 R /XYZ 0 841.88 null ] /Parent 51 0 R >> endobj 53 0 obj << /Dest [ 9 0 R /XYZ 0 841.88 null ] /Count 0 /Title (Page 3) /Parent 51 0 R >> endobj 52 0 obj << /Dest [ 9 0 R /XYZ 0 841.88 null ] /Count 0 /Title (Page 3) /Parent 51 0 R >> endobj 49 0 obj << /Last 52 0 R /Count -1 /First 53 0 R /Title (Page 2) /Dest [ 6 0 R /XYZ 0 841.88 null ] /Parent 51 0 R >> endobj 47 0 obj << /Last 49 0 R /Count -1 /First 50 0 R /Title (Page 1) /Dest [ 2 0 R /XYZ 0 841.88 null ] /Parent 51 0 R >> endobj(The Parent of all the outline objects is given as object 51, which is blank. The First/Last objects don't link correctly to the expected hierarchy, etc, etc.) Acrobat preflight will flag this as a syntax error, though the bookmarks do largely function in most viewers. Preview doesn't show the top-level outline, though that might relate to FB4013726, filed in 2018. I have shown the created syntax to ChatGPT, which also confirmed that the syntax does not conform to the expected PDF spec: This isn’t simply a matter of PDFKit choosing an unnecessarily elaborate but valid representation. There are genuine structural problems: The top-level Page 1 object’s /Parent does not point to the /Outlines dictionary. The child objects’ /Parent does not point to their actual containing outline. There are duplicate outline objects for Page 1, Page 2 and Page 3. The required sibling Prev/Next chains are absent. The /First//Last relationships don’t correspond cleanly to the claimed hierarchy. The errors are entirely reproducible in any PDFOutlines created by PDFKit. I have filed this as FB25328043. ... and in 2021 as FB8960602. ... and in 2019 as FB5313583.
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
2
Boosts
0
Views
334
Activity
13h
NSScrollView: Overriding "scrollWheel(with:)" can cause a never-ending live scroll
Overview I'm developing an app that depends on NSScrollView to implement a scrollable and zoomable canvas. I need to override NSScrollView.scrollWheel(with:) to implement Option-zooming (holding Option while scrolling up/down to zoom in/out). I've found that simply adding these three lines of code in my NSScrollView subclass: override func scrollWheel(with event: NSEvent) { super.scrollWheel(with: event) }is enough to cause a live scroll to never end, and NSScrollView.didEndLiveScrollNotification to never fire. My app depends on that notification firing so that it can disable some interactions during a live scroll. Furthermore, while the NSScrollView is "stuck" in the live scroll, it's not possible to perform a live magnify. There are also some other effects, including elevated CPU usage and persistent scroll indicators. The issue is occurring with Xcode 27.1 (27A9275) and macOS 27.2 (26B123). I have modified the macOS App project template to showcase the issue. The sample project, along with a screen recording of the issue, can be downloaded from here: https://drive.google.com/drive/folders/1F5sF2NA230NkGbQdLfbV6vM1XmfY1-uT?usp=sharing I hope that Apple can fix this issue soon, as it's a frustrating user experience when the canvas gets stuck while scrolling. I've already filed this in Feedback Assistant under FB25362729. Steps to Reproduce To recreate the issue, follow these steps: Download and extract the "Xcode Project.zip" file from the link above. Open the extracted "NSScrollViewTest" project in Xcode. Build and run the "NSScrollViewTest" app. Scroll all the way to the right edge of the gray canvas using the horizontal scroll gesture on Magic Trackpad. If you comment out lines 8–10 of ScrollView.swift, the issue goes away. The "Issue Recording.mov" file from the link above provides a detailed video of how to recreate the issue.
Topic: UI Frameworks SubTopic: AppKit
Replies
9
Boosts
0
Views
596
Activity
15h
iOS 27 regression - minimized search item in top toolbar breaks its state
struct ContentView: View { @State var searchText: String = "" var body: some View { TabView { Tab { NavigationStack { List { Text("Hello!") Text("Hello!") Text("Hello!") Text("Hello!") Text("Hello!") Text("Hello!") } .navigationTitle("Have a title") .searchable(text: $searchText, placement: .toolbar) .searchToolbarBehavior(.minimize) .toolbar { DefaultToolbarItem(kind: .search, placement: .topBarTrailing) } } } } } } In iOS 26, this worked no problem. In iOS 27, this leaves the search bar either unable to collapse (when pressing the close button) or in a broken state where it cannot be opened again.
Topic: UI Frameworks SubTopic: SwiftUI
Replies
8
Boosts
11
Views
1.7k
Activity
15h
Workaround for NSTableView bugs introduced in macOS 27
MacOS 27 (or perhaps 26, I never used it) introduces two bugs in NSTableView (and delegate). It's always a pleasure when you find that your app no longer works properly. First, when the delegate responds to tableView:pasteboardWriterForRow:, no row can be selected by click & drag (even if the method returns nil). Which mean that clicking and dragging the mouse on rows that are not draggable simply does nothing (no selection), which is a frustrating user experience, especially considering that the same action selects rows on macOS 15. The second bug is that tableView.verticalMotionCanBeginDrag = NO is simply ignored. It doesn’t work. So, a click followed by an immediate vertical drag drags the clicked row instead of selecting rows if tableView:pasteboardWriterForRow: does not return nil. Again, it did select rows on macOS 15. That's what verticalMotionCanBeginDrag = NO is for. To work around the first bug, I implement respondsToSelector: in the delegate to return NO when the selector is tableView:pasteboardWriterForRow: and the clicked row is not draggable. This solution is not elegant, as theclickedRow property of the tableview always returns -1 when the method is called. Which means I need to determine the clicked row by other means (using the mouse location and stuff). (This solution should in principle allow working around the second bug, but I haven’t implemented it yet. It would require determining the delay between the click and the drag and the direction of the drag). So my question is: does anyone see a better workaround for these bugs?
Topic: UI Frameworks SubTopic: AppKit
Replies
3
Boosts
0
Views
186
Activity
16h
XCTest Feature request: Open/close and rotate iPhone Duo devices
Currently, we do not have a way to open, close and rotate iPhone Duo devices via XCUITest test automation. Please provide a way to perform these operations via XCTest. XCUIDevice.shared.orientation has no effect on an iPhone Duo iOS 27.1 simulator. We could open, close and rotate an iPhone Duo simulator manually via the Device Hub at the moment.
Replies
0
Boosts
0
Views
92
Activity
17h
NavigationSplitView Binding to NavigationSplitViewColumn reset with every NavigationStack path change
I try to create a Navigation that works on iPhone, iPhone Duo and iPad. NavigationSplitView collapses for compact form factors and makes iPhone Duo support much simpler. The Problem is the semantic of the collapse. Switch from detail to sidebar on compact is not a 'back' action in my case. It should have my choosen Icon and has a meaning. So i wanted to control this using the NavigationSpliViewColumn Binding. This does work forward and backward as long as no NavigationStack was used before. But it stops working when you return to the detail root from a Navigation-Action. I left the Backbutton visible so you can test, that it continues to work, when no Navigation-Action preceeded the switch. Here is my Code: import SwiftUI @Observable final class Compass { var path: [Route] init() { self.path = [] } } enum Route: Hashable { case goal } struct ContentView: View { @Environment(\.horizontalSizeClass) private var hsize @State private var compass: Compass = Compass() @State var column: NavigationSplitViewColumn = .detail var body: some View { NavigationSplitView(preferredCompactColumn: $column) { OverviewScreen(column: $column) } detail: { TodayScreen() .toolbar { ToolbarItem(placement: .topBarLeading) { Button("overview", systemImage: "calendar") { self.column = .sidebar } } } } .environment(compass) .onChange(of: column) { old, new in print("column:", old, "→", new) } } } struct OverviewScreen: View { @Binding var column: NavigationSplitViewColumn @Environment(Compass.self) var compass var body: some View { @Bindable var compass = self.compass ScrollView { Text("Overview") .font(.largeTitle) .fontWeight(.heavy) Button("Switch") { self.column = .detail } } } } struct TodayScreen: View { @Environment(Compass.self) var compass var body: some View { @Bindable var compass = self.compass NavigationStack(path: $compass.path) { ScrollView { Text("Today") .font(.largeTitle) .fontWeight(.heavy) Button("Goals programtically", systemImage: "flag.fill") { self.compass.path = [.goal] } NavigationLink(value: Route.goal) { Label("Goal Link", systemImage: "flag.fill") } } .navigationDestination(for: Route.self, destination: self.screen) } } @ContentBuilder func screen(for route: Route) -> some View { switch route { case .goal: Text("Goals") } } } #Preview { ContentView() }This seems unexpected behaviour. If you ask AI the mental model is NavigationSplitViewColumn represents which column is currently visible for the user. That model would be wrong. Also i can't understand why a NavigationStack has to change the Binding? What am i missing here? Is my idea of the programmatic switch not supported? There are other ways to push from compact to your detail column again, but they all have trade-offs or run into other problems. I would appreciate any help here. AI has not understood this and only does surface level work arounds that fix nothing.
Replies
0
Boosts
0
Views
22
Activity
1d
Keyboard Toolbar Padding iOS26
When I create a SwiftUI toolbar item with placement of .keyboard on iOS 26, the item appears directly on top of and in contact with the keyboard. This does not look good visually nor does it match the behavior seen in Apple's apps, such as Reminders. Adding padding to the contents of the toolbar item only expands the size of the item but does not separate the capsule background of the item from the keyboard. How can I add vertical padding or spacing to separate the toolbar item capsule from the keyboard?
Topic: UI Frameworks SubTopic: SwiftUI
Replies
12
Boosts
9
Views
2.1k
Activity
1d
UITableView row reordering no longer works under macOS 27 with Mac Catalyst
Under macOS 27 using Mac Catalyst for a UIKit-based app, If you present a view controller with a table view as a form sheet or page sheet, row reordering fails to function. You can drag a row as expected but the blue movement bar never appears and if you drop the row it simply returns to its original location. The exact same view controller presented as a popover works just fine. The exact same view controller not presented as a modal (such as the app's root controller) works just fine. This is a serious bug affecting existing applications and being reported by paying customers. This has been reported as FB25038883 which includes a simple sample app demonstrating the issue.
Replies
2
Boosts
0
Views
413
Activity
1d
NSSegmentedControl style ineffective.
I'm not sure if it's something wrong with my XCode install (Version 27.1, macOS 27.2) or what, because such a serious issue should be mentioned already... Basically, building my objC app with the latest XCode makes the NSSegmentedControl style ineffective. Likewise, changing the style in the attribute of the control in interface builder has no visible effect on the preview either. Changing the style in code or in IB has no effect. The control appears stuck with a style that implements a blue background for the selected segment (some default style I guess). I tried with a minimalistic app that includes only one window and the control. The issue is still present. Any suggestion? Am I the only one experiencing this?
Topic: UI Frameworks SubTopic: AppKit
Replies
8
Boosts
0
Views
464
Activity
1d
Clipped render of dragged NSTableView row on macOS 27.
On macOS 27, dragged rows on my app's table views are excessively clipped (see image). I don't override methods like `tableView:draggingSession:willBeginAtPoint:forRowIndexes:` so I don’t supply my own drag images, and I don’t use NSTableView suclasses. I tried on a toy project containg with a single table view in a window, and it did not reproduce this behavior. I wonder if my issue if it’s due to my app’s table views being embedded in split views or something. Anyway, how can I fix that?
Topic: UI Frameworks SubTopic: AppKit
Replies
0
Boosts
0
Views
171
Activity
1d
NSScrollView scrolling hitch
When scrolling a basic NSScrollView there seems to be a sudden jump after each flick. Scrolling does not appear smooth and is disorientating. A scroll jump seems to happen directly after letting go of a scroll flick using a trackpad/mouse. Right at that moment the scroll turns into a momentum scroll, slowly decreasing the speed. But the first frame after the gesture the content jumps forward, more than what is expected. Observations: Counterintuitively, scrolling appears to be smoother when disabling NSScrollView.isCompatibleWithResponsiveScrolling. If disabled using a custom NSScrollView subclass there is no large jump anymore. Scrolling also appears to be smoother using a SwiftUI ScrollView. I assume that has the same behaviour as a disabled isCompatibleWithResponsiveScrolling Ironically a WKWebView scrolls much smoother. No sudden jump is observable. It also seems to scroll with faster acceleration, but the individual frames do appear smoother. Why is this better than a native NSScrollView? Elastic scrolling at the bounds of the scroll view also appears much smoother for WKWebViews. When pulling to refresh there is a jump for NSScrollView/SwiftUI, but not for WKWebView. When using an NSScrollView with isCompatibleWithResponsiveScrolling disabled, scrolling appears just as smooth as WKWebView on macOS 13 Ventura and below. On macOS 14 Sonoma scrolling behaviour is suddenly different. Please see a sample project with 4 different scroll views side by side: https://github.com/floorish/ScrollTest Screen recordings show the sudden jumps when scrolling and when elastic scrolling. Tested on Intel & Arm Macs, macOS 11 Big Sur through 15 Sequoia, built with Xcode 16. Should isCompatibleWithResponsiveScrolling be disabled on Sonoma+? Are there any drawbacks? There is also no overdraw anymore since Monterey, as described in https://developer.apple.com/library/archive/releasenotes/AppKit/RN-AppKitOlderNotes/#10_9Scrolling Even with responsive scrolling disabled, why is WKWebView scrolling much smoother than NSScrollView?
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
9
Boosts
3
Views
1.4k
Activity
1d
What pattern to use for an iPhone Tabview app
I have an iPhone tab view application that has not been designed for iPad, and I am aiming to add a left-hand bar that summarises some content and keeps visible what is normally a sheet. What pattern would work best for this? At present, I pass the view to another view with a navigation stack containing an arrangement view with the previous view and then the sidebar as a secondary view within it—would that be the appropriate approach?
Topic: UI Frameworks SubTopic: SwiftUI
Replies
3
Boosts
0
Views
392
Activity
1d
State Restoration no longer works in a Mac Catalyst based app when run on macOS 27.x
As reported in FB25363417: A UIKit based app running on macOS 27.2 (or macOS 27.0.1) via Mac Catalyst no longer has functioning state restoration. Upon app restart, there is no NSUserActivity being provided to the scene in the UISceneDelegate method scene(_:willConnectTo:options:). This can be tested with Apple’s own sample app “Restoring your app’s state”. Just update the sample project with support for a Mac Catalyst build. Using Xcode 27.2 on a Mac with macOS 27.0 or 27.2, build and run the Mac Catalyst version of the app. The main screen appears with a list of products. Select any product so you see details of the product. Quit the app. Run the app again. Note that you are not returned to the previously selected product detail screen. Instead, you just see the main list of products. If you run the same app and perform the same steps on a Mac running macOS 26.x, then when the app is restarted, you correctly get returned to the previously selected product detail screen. The problem is being caused by no NSUserActivity being passed into the scene delegate on app startup. While running the app on a Mac with macOS 27.x, put a breakpoint on the initial guard statement in scene(_:willConnectTo:options:) and you will see there is no activity on app restart. This is impacting paid customers of my existing app since upgrading to macOS 27. They no longer get returned to the app’s previous state when restarting the app. It is expected that state restoration should work on macOS 27 just as well as it does under macOS 26 in an app built with Mac Catalyst.
Replies
0
Boosts
0
Views
75
Activity
1d
UIKIt, iOS 27, UIDocumentPickerViewController(forExporting: [fileURL])
My App saves files using the UIDocumentPickerViewController. This works from iOS 17 to 26. Usually, you have a file with a given name in your sandbox, which you can then export via the pickerVC. In the pickerVC you change the name. In iOS 27 the file name is greyed-out and you can't change it here. The file can be exported only with the pre-given name. Is this a new behaviour or bug in iOS 27?
Topic: UI Frameworks SubTopic: UIKit
Replies
0
Boosts
0
Views
83
Activity
1d
UITextContentType.cellularIMEI works on iOS 27+ only
During testing, we found that IMEI AutoFill behaves differently by iOS version, independent of the entitlement, and would like to confirm the expected behavior. Test details Implementation: textContentType = .cellularIMEI on the IMEI input field Entitlement status: no carrier-related entitlements in the test build Observed results iOS 27: The IMEI AutoFill suggestion appears and works in any app, regardless of carrier entitlement. iOS 26 and earlier: The IMEI AutoFill suggestion does not appear. Questions Is it the expected and intended behavior that, on iOS 27, IMEI AutoFill is available to any app without a carrier entitlement? On iOS versions earlier than 27 (iOS 17.4 to 26), is the public cellular plan entitlement required for IMEI AutoFill to work? If not, are there other conditions or requirements? On dual-IMEI devices, which IMEI (IMEI or IMEI2) is filled when .cellularIMEI is used on iOS 27? Should we use .cellularIMEI1 / .cellularIMEI2 to specify it explicitly? Thank you for your support.
Replies
1
Boosts
0
Views
86
Activity
2d
UIKit snapshot views render empty into UIImage on physical devices, but work in Simulator
Is there a supported way to convert the cached contents of a UIKit snapshot view into a UIImage on physical iOS/iPadOS devices? A view returned by snapshotView(afterScreenUpdates:) displays correctly on hardware, but drawing that view into a UIGraphicsImageRenderer produces no cached-content pixels. drawHierarchy(in:afterScreenUpdates:) still returns true. The same base experiment succeeds in Simulator. Feedback Assistant report: FB25336445. A standalone reproducer and measurements are attached there; use the corrected replica-readback-ios-27.0.1-fixed-project.zip attachment. Tested environments Physical iPhone 15 Pro Max: iOS 27.0.1 (24A446). Physical iPad mini (6th generation): iPadOS 26.6.1 (23G83). Two independent app launches produced identical measurements. Simulator: iPhone 18 Pro / iOS 27.0 and iPhone 15 Pro Max / iOS 26.1. The app is a standalone UIKit Release build, launched without a debugger or XCTest. It uses an ordinary red UIView and a white UILabel: no WebKit, Liquid Glass, video, secure text fields, third-party libraries, or private API calls. I have not tested a physical iPhone on the 26 series or iOS 27.0.2. The Simulator and device OS patch versions differ, so this is not a controlled OS-only comparison. Reproduction Display a red 240 x 160 UIView containing a white UILabel; allow it to render. Draw the original view into an image as a positive control. Call source.snapshotView(afterScreenUpdates: false), attach the replica to the window at the source frame, wait 500 ms, hide the original, then wait another 500 ms. Draw the attached replica into transparent and cyan-prefilled image contexts. Add an ordinary red 30 x 30 child UIView to the replica, wait 500 ms, and capture again. Repeat with replicas from UIWindow.snapshotView and UIScreen.snapshotView. This is the capture operation, called on the main actor after those waits: func rasterize(_ target: UIView, cyanBackground: Bool) -> UIImage { let format = UIGraphicsImageRendererFormat() format.scale = 1 format.opaque = false return UIGraphicsImageRenderer(size: target.bounds.size, format: format) .image { context in if cyanBackground { UIColor.cyan.setFill() context.fill(target.bounds) } let success = target.drawHierarchy( in: target.bounds, afterScreenUpdates: true ) print("drawHierarchy:", success) } }Results On both physical devices: The original 240 x 160 UIView renders normally: all 38,400 pixels are nontransparent. The replica on a transparent target produces zero nontransparent pixels. The replica on a cyan target leaves all 38,400 pixels cyan. Adding an ordinary child view produces approximately 900 red pixels, but the replica's cached contents are still missing. UIView, UIWindow and UIScreen replicas all exhibit the omission, while drawHierarchy returns true. In both tested Simulators, the base experiment renders the replica contents and overwrites the cyan background. The child-marker addition was tested on physical devices only. These counts are measured from the CGImage before PNG encoding. Thus “black output” with an opaque context appears to be missing content, not pixels painted black: transparent and cyan targets retain their original contents. Questions Is bitmap readback of these snapshot views supported on physical devices, or are they only intended for on-screen composition? If unsupported, is the Simulator behavior expected, and why does drawHierarchy return success despite omitting the visible cached contents? Is there a supported API to materialize those cached contents as an image, without starting a screen-recording session? Capturing the original view directly is a useful control, but does not answer how to read back an already-created snapshot. I found this older AVSampleBufferDisplayLayer discussion, which also describes a correctly displayed snapshot view becoming black when converted to an image. My reproducer uses only ordinary UIKit views; I do not know whether the underlying cause is related.
Topic: UI Frameworks SubTopic: UIKit
Replies
5
Boosts
0
Views
338
Activity
2d
Best way to position game touch controls around the iPhone Duo hinge
For a full-screen game with a Metal/Unreal rendering view and a SwiftUI overlay for touch controls, what is the recommended way to keep interactive controls away from the hinge while still allowing the rendered game world to use the full display? Would you recommend querying ReservedRegion in the SwiftUI overlay while allowing the underlying render view to remain edge-to-edge? Also, should control placement respond continuously while the device is being folded, or primarily respond to layout/reserved-region changes once the pose changes?
Topic: UI Frameworks SubTopic: SwiftUI
Replies
1
Boosts
0
Views
83
Activity
2d