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

iOS 27: ScrollViewProxy.scrollTo no longer reaches unrealized LazyVStack rows; how to preserve position when prepending?
I have a chat screen built with ScrollView { LazyVStack } and ScrollViewReader. Two things that worked through iOS 26 stopped working on iOS 27 (Xcode 27, iOS 27.0 simulator and device; unchanged code still works on the iOS 26.x simulator): Open at the newest message. On appear I call proxy.scrollTo(lastId, anchor: .bottom). On iOS 27 the list stops two or three rows above the bottom when the rows have variable heights (text bubbles mixed with 200pt images). Load older messages at the top without the list jumping. When the user reaches the top, I prepend 25 older messages and call proxy.scrollTo(previousTopId, anchor: .top) so the row they were reading stays put. On iOS 27 the call does nothing: the list stays at the top of the newly inserted page (offset stays at 0), which immediately re-triggers the load. Re-issuing scrollTo on every layout change for a short window (which is what made this reliable on iOS 26) has no effect on iOS 27. Minimal reproduction import SwiftUI struct Message: Identifiable, Hashable { let id: Int let height: CGFloat // simulates text vs. image bubbles } @MainActor final class ChatModel: ObservableObject { @Published var messages: [Message] = [] @Published var previousTopId: Int? // set when a page is prepended private var nextOldId = 1_000 init() { messages = (0..<25).map { Message(id: nextOldId - $0, height: Self.randomHeight()) }.reversed() nextOldId -= 25 } func loadOlder() { let top = messages.first!.id let page = (0..<25).map { Message(id: nextOldId - $0, height: Self.randomHeight()) }.reversed() nextOldId -= 25 messages.insert(contentsOf: page, at: 0) previousTopId = top // "keep this row at the top" } static func randomHeight() -> CGFloat { [44, 60, 90, 200, 260].randomElement()! } } struct ChatView: View { @StateObject private var model = ChatModel() var body: some View { ScrollViewReader { proxy in ScrollView { LazyVStack(spacing: 8) { // top sentinel: load older when it becomes visible Color.clear.frame(height: 1) .onAppear { model.loadOlder() } ForEach(model.messages) { m in RoundedRectangle(cornerRadius: 12) .fill(m.height >= 200 ? .orange.opacity(0.4) : .blue.opacity(0.3)) .frame(height: m.height) .overlay(Text("\(m.id)")) .padding(.horizontal) .id(m.id) } } } .onAppear { // (1) open at the newest message DispatchQueue.main.async { proxy.scrollTo(model.messages.last!.id, anchor: .bottom) } } .onChange(of: model.previousTopId) { _, id in // (2) restore the row that was at the top before the prepend guard let id else { return } DispatchQueue.main.async { var t = Transaction(); t.disablesAnimations = true withTransaction(t) { proxy.scrollTo(id, anchor: .top) } } } } } } Observed (1) Open at the newest message, scrollTo(lastId, anchor: .bottom) iOS 26.x: lands on the last row. iOS 27.0: stops 2–3 rows above the bottom. (2) Prepend 25 rows, then scrollTo(previousTopId, anchor: .top) iOS 26.x: the previous top row is at the top of the viewport. iOS 27.0: the offset stays at 0 and the new page's first row is at the top. What I have tried on iOS 27 Re-issuing scrollTo for 0.5s on every content-height or offset change (via GeometryReader preferences). No effect; the target row is not realized, and the visible rows are kept stable instead. .defaultScrollAnchor(.bottom) and .defaultScrollAnchor(.bottom, for: .sizeChanges): fixes the initial open, but the stored anchor is re-applied once on the first content change (the prepend), which snaps the list to the newest message. .sizeChanges did not preserve the prepend. .scrollPosition(id: $topId, anchor: .top) with .scrollTargetLayout() on the LazyVStack: the binding tracks the top row correctly, but after the prepend SwiftUI re-targets the binding to the new page's first row. Writing the previous id back, in the same update or on later run-loop turns, does not restore the position. Replacing LazyVStack with VStack fixes both cases, but the list holds hundreds of image rows and needs the lazy container for memory. What does work: reaching the backing UIScrollView (SwiftUIIntrospect), recording the visible rows' frames before the insert and adjusting contentOffset after layout. It works but is a lot of code for something that used to be one scrollTo. Questions Is it intended on iOS 27 that ScrollViewProxy.scrollTo does not scroll to a LazyVStack row that is not currently realized, or that the lazy stack keeps the currently visible rows stable in preference to the requested target? The WWDC26 lazy-stacks session describes the stack and scroll view coordinating the offset as estimates update; is scrollTo to an unrealized row now unsupported? Is there a supported SwiftUI way on iOS 27 to keep the visible rows in place when items are prepended to a LazyVStack, or to scroll reliably to an unrealized row? For example a ScrollPosition usage or an anchor role I am missing. If not, is adjusting the UIScrollView offset the expected approach, or is List now the recommended container for chat-style lists with bidirectional paging? I have filed this as FB24968838 with the sample project attached.
0
0
56
1d
iOS 27: swipeActions outside List never re-evaluates its content closure (stale labels, if gating ignored) — intended?
We are adopting the iOS 27 support for swipeActions on rows inside a ScrollView { LazyVStack } (with swipeActionsContainer() on the scroll view). We expected the row modifier to behave like it does inside List, but on iOS 27.0 (24A437, iPhone 17; also 27.0 simulator) the content closure appears to be evaluated only once, when the row is first registered, and never again while the row stays on screen. Is this the intended behavior, or a bug? What we observe Stale button labels / actions. A button whose title depends on state (Button(isPinned ? "Unpin" : "Pin")) keeps its first title after the state changes. The row body itself re-renders with the new state, but the swipe actions do not, until the row is recycled by the lazy stack (scroll it off-screen and back) — then it shows the new value. Conditional content is ignored. swipeActions { if !editing { Button(...) } } keeps showing the buttons after editing becomes true, and the row can still be swiped. Views placed inside the content that observe state themselves (an @Observable/@ObservedObject child view) do update their text. But an if inside that child view does not remove the buttons, and emptying a ForEach inside it removes the buttons while the row still slides open (onPresentationChanged fires with true). onLongPressGesture(minimumDuration: 0.7) on the same row fires only on touch-up (after ~3 s of holding) when the row has swipe actions in a ScrollView; inside List, and in a ScrollView without swipe actions, it fires at ~0.7 s while still pressed. The same row code inside List behaves as expected for all four points. Attaching or omitting swipeActionsContainer() and using the old swipeActions(edge:allowsFullSwipe:content:) overload instead of the new onPresentationChanged overload makes no difference. Minimal reproduction (iOS 27 only, single file) import SwiftUI @Observable final class Model { var editing = false var pinned: Set<Int> = [] } @available(iOS 27, *) struct ContentView: View { @State private var model = Model() @State private var lastLongPress = "-" var body: some View { VStack(spacing: 8) { Toggle("Editing (swipe should be off)", isOn: $model.editing) Text("long press: \(lastLongPress)").font(.caption) ScrollView { LazyVStack(spacing: 0) { ForEach(1...30, id: \.self) { n in HStack { Text("Row \(n)") Spacer() Text(model.pinned.contains(n) ? "pinned" : "").foregroundStyle(.secondary) } .frame(height: 56) .contentShape(Rectangle()) .onLongPressGesture(minimumDuration: 0.7) { lastLongPress = "row \(n) @ \(Date().formatted(date: .omitted, time: .standard))" } .swipeActions(edge: .trailing, allowsFullSwipe: false) { if !model.editing { // (2) ignored after first registration Button(model.pinned.contains(n) ? "Unpin" : "Pin") { // (1) title stays "Pin" if model.pinned.contains(n) { model.pinned.remove(n) } else { model.pinned.insert(n) } } .tint(.blue) } } onPresentationChanged: { _ in } } } } .swipeActionsContainer() } .padding(.horizontal) } } Steps: Swipe row 3, tap Pin. The row shows "pinned". Swipe row 3 again → the button still says Pin (in List it says Unpin). Tapping it runs the closure with the current model, so it unpins, but the label was wrong. Turn Editing on, swipe any row → it still opens with the button (in List it does not open). Press and hold a row for 3 s → "long press" timestamp is written only when the finger lifts. Questions Is "evaluate the swipeActions content once per row registration" the intended contract for swipe actions outside List? The documentation for swipeActionsContainer() only describes coordination (single open row, dismiss on scroll / outside tap), and swipeActions(edge:allowsFullSwipe:content:) doesn't mention any difference between List and other containers. If it is intended, what is the recommended way to (a) disable swipe for a row temporarily (e.g. during an edit mode) and (b) update button titles from state, without recreating the row view? We currently work around it with a child view that observes the model for titles, and allowsHitTesting(false) on the row to disable swiping, but both feel like they rely on undocumented behavior. Is the delayed onLongPressGesture (fires on touch-up) expected when a row carries swipe actions in a ScrollView? simultaneousGesture(LongPressGesture(...)) fires while pressed, which suggests the swipe recognizer imposes a failure requirement on the row's gestures.
0
0
55
1d
Honored Interface Orientations on the iPhone Duo Inner Display
Hello, In Apple’s Tech Talk Prepare your app for iPhone Duo, Apple mentions that on the Duo internal display, supported interface orientations are not honored unless UIRequiresFullScreen is enabled, in which case the app is scaled. I first tested the behavior described by Apple. With UIRequiresFullScreen enabled, I returned .portrait from UIWindowSceneDelegate.supportedInterfaceOrientations(for:), added only UIInterfaceOrientationPortrait in Info.plist, and the app remained upright, using letterboxing as needed, which matched Apple’s description. However, if I add all interface orientations in Info.plist while the scene delegate still returns .portrait, the app becomes fullscreen and locked in portrait orientation, like a portrait-only app, which seems to diverge significantly from the behavior described in the Tech Talk. I then tested most possible combinations and observed five distinct behaviors: Normal: Auto-rotated, always fullscreen B-Portrait: Auto-rotated, fullscreen in portrait; portrait letterboxed in landscape B-Landscape: Auto-rotated, fullscreen in landscape; landscape letterboxed in portrait L-Portrait: Locked in portrait L-Landscape: Locked in landscape But no rule seems to explain how a given combination determines the resulting behavior. Not even AI could figure out a sane one. Does anyone have any idea how this works?
Topic: UI Frameworks SubTopic: UIKit
0
0
38
1d
Charts are broken with Xcode 27, Plotting multiple lines
Hi, Charts—specifically those with multiple lines—are broken in Xcode 27. First, I spotted the bug in my program, and then I checked your example. Your own example Plotting-multiple-lines is not working correctly anymore. It shows 1 line or sometimes no lines at all, depending on the order of the data. It depends on how the data is passed to the chart. If the data is passed as separate series, it works. In Visualizing your app’s data it works, but the data is passed as described before. Don't follow Microslop: have the AI ​​generate the code and then skip the tests. This is a serious bug that requires a lot of work to rearrange the data, just to work around the issue. Christian
2
0
247
1d
UINavigationBarAppearance background does not extend to the top edge on iPhone Duo
Environment Xcode 27.1 iOS 27.1 iPhone Duo simulator UIKit app built with the iOS 27.1 SDK Issue On iPhone Duo, the background of a system-managed UINavigationBar does not extend completely to the top edge of the window. The navigation bar is configured using UINavigationBarAppearance with an opaque blue background. However, a horizontal white strip remains above the blue navigation bar. I also post a feedback: FB24859353 Questions Is this expected behavior on iPhone Duo? What is the recommended way to style this top region? Should apps add a custom background underlay outside the UINavigationBar bounds? Could this be an iOS 27.1 or iPhone Duo simulator issue? Minimal reproduction code: import UIKit final class DemoTabBarController: UITabBarController { override func viewDidLoad() { super.viewDidLoad() viewControllers = NavigationBarStyle.allCases.map { style in let content = DiagnosticsViewController(style: style) let navigationController = UINavigationController(rootViewController: content) navigationController.tabBarItem = UITabBarItem( title: style.title, image: UIImage(systemName: style.symbolName), selectedImage: nil ) style.apply(to: navigationController.navigationBar) return navigationController } } } enum NavigationBarStyle: CaseIterable { case systemDefault case appearance case legacy var title: String { switch self { case .systemDefault: return "Default" case .appearance: return "Appearance" case .legacy: return "Legacy" } } var symbolName: String { switch self { case .systemDefault: return "iphone" case .appearance: return "paintbrush" case .legacy: return "clock.arrow.circlepath" } } func apply(to navigationBar: UINavigationBar) { switch self { case .systemDefault: break case .appearance: let appearance = UINavigationBarAppearance() appearance.configureWithOpaqueBackground() appearance.backgroundColor = .demoBlue appearance.shadowColor = nil appearance.titleTextAttributes = [.foregroundColor: UIColor.white] navigationBar.tintColor = .white navigationBar.standardAppearance = appearance navigationBar.compactAppearance = appearance navigationBar.scrollEdgeAppearance = appearance case .legacy: navigationBar.tintColor = .white navigationBar.barTintColor = .demoBlue navigationBar.backgroundColor = .demoBlue navigationBar.setBackgroundImage(Self.solidImage(color: .demoBlue), for: .default) navigationBar.shadowImage = UIImage() navigationBar.isTranslucent = false navigationBar.titleTextAttributes = [.foregroundColor: UIColor.white] } } private static func solidImage(color: UIColor) -> UIImage { return UIGraphicsImageRenderer(size: CGSize(width: 1, height: 1)).image { context in color.setFill() context.fill(CGRect(x: 0, y: 0, width: 1, height: 1)) } } } private extension UIColor { static let demoBlue = UIColor(red: 0.0, green: 0.46, blue: 0.70, alpha: 1.0) }
2
1
292
1d
Can a Notes note be dragged into another app on iPhone Duo?
I’m adding drag-and-drop support to my app for multitasking on iPhone Duo. My app supports text/note content. Currently, a user can move content from Apple Notes into my app using Share or Copy/Paste. ** Questions** Can a note from the Notes app be dragged directly into another app during multitasking, similar to dragging a photo? If so, what content type does Notes provide through the drag-and-drop session? For example, is the note exposed as plain text (public.plain-text / UTType.plainText), rich text, or another transferable type? My goal is for the user to drag a note from Notes into my app and have it behave essentially like Copy → Paste, without requiring the Share sheet. Thank you.
0
0
76
2d
SwiftUI Document API Duplicate Function hangs on macOS 27
In a macOS 27 app using DocumentGroup(editor:makeDocument:) with a type conforming to the new Document protocol, choosing File › Duplicate hangs the app permanently (0% CPU, spinning beach ball, must force quit). The main thread is blocked in URLPlatformDocument.read(from:ofType:) waiting on a dispatch semaphore. That synchronous NSDocument read path is reached from NSDocumentController.duplicateDocumentWithContentsOfURL(:copying:displayName:) → makeDocumentForURL(:withContentsOf:ofType:) → NSDocument.init(for:withContentsOf:ofType:). The work the semaphore waits for never runs: the app's makeDocument closure is never called. The SDK declares makeDocument and ReadableDocument.apply(snapshot:previous:) as @MainActor, so blocking the main thread while waiting for them can never complete. This reproduces with Apple's unmodified sample code project "Building a Document-Based App with SwiftUI" (no code or project changes; only a signing team set). Our own app, which uses a custom DocumentReader/DocumentWriter with Source/Destination == URL, hangs with the identical stack. Has anyone found any workaround? Filed Feedback FB24949862
Topic: UI Frameworks SubTopic: SwiftUI
0
0
63
2d
sidebarAdaptable Design Problem
This is what Apple's Destination Video Sample App looks like on iPhone Duo built with SDK 27.1 beta. Two things: Items that should not appear in the tab bar appear. There is no sidebar for iPhone Duo. So my problem is: is this a bug or a design on purpose? Will sidebarAdaptable gets a sidebar on iPhone Duo? Or at least, how to hide these things that should only appear in the sidebar? The sample app uses .defaultVisibility(, for:) and .hidden() but obviously none of these takes effect.
Topic: UI Frameworks SubTopic: SwiftUI
1
1
186
2d
How to check for multiple scene support on iPhone Duo?
I have an iOS app that supports multiple scenes on the iPad, and which has an "Open in Another Window" feature which creates a new window scene. I would like to bring this feature to the iPhone Duo. On the iPhone Duo, of course, creating new windows is only supported when the device is open; when it is closed, creating new windows does not work. (If you try, an error is thrown.) Until now, the way I have checked whether my "Open in Another Window" feature should be available is to check to see if UIApplication.shared.supportsMultipleScenes is true. This has always returned false for previous iPhones and true for iPads. Unfortunately, however, this does not work as expected on the iPhone Duo. On the Duo, I would expect supportsMultipleScenes to return true when the device is open, but false when it is closed. This is not the case: it returns true for all poses. (Filed as #FB24948411 as this doesn't seem right to me.) So it does not help me decide whether the feature should be available. UIWindowScene.ActivationAction does work as expected when used in a menu, with the action auto-hiding when the Duo is in the closed pose. In my app, though, I need more than just an auto-hiding menu item; I need to check whether creating a new window is currently possible for certain UI availability decisions. What, then, is the correct way of checking this, if it's not with supportsMultipleScenes? Given that UIWindowScene.ActivationAction is able to hide itself, I assume there is some better way of checking that I have missed.
Topic: UI Frameworks SubTopic: UIKit Tags:
0
0
70
2d
Supported way to put an iPhone Duo simulator into the unfolded state programmatically
The Duo simulator boots showing only the outer display: the window is fixed at 382×644 pt and our layout classifier always reports the compact stack mode. We measured this on two separate clean boots (shutdown, erase, boot). xcrun simctl help lists no subcommand for folding, posture, or selecting the inner display — we read the full list. xcrun simctl io screenshot does reveal a second display (LCD-1, 2007×2853 px, aspect 0.70, close to the 669×951 inner portrait size). Unfolding manually in the Simulator UI works and the app then renders the two-column layout correctly, but we could not find a programmatic equivalent. Is there a supported way to unfold a Duo simulator from the command line or from XCTest?
Topic: UI Frameworks SubTopic: SwiftUI
3
3
751
3d
Enable iPhone Duo Upside Down Orientation
Ever since the iPhone X, upside-down orientation on the iPhone has been disabled by design. I haven't found any official documentation explaining why, but my guess is it has to do with Face ID and the top notch. However, now that the iPhone Duo has no Face ID or notch—and includes reserved occlusion regions—why not enable upside-down rotation? As of iOS 27.1, it remains disabled. Leaving it turned off only confuses users, making them think their favorite apps are frozen when they won't rotate.
Topic: UI Frameworks SubTopic: SwiftUI
1
1
330
3d
iPhone Duo and the Safe-Area
I took a screenshot of the Safety Area's and Occlusions on the iPhone Duo outer display. The article Designing for iPhone Duo tells us to... Consider using the full display width for interfaces where bars aren’t necessary. Some layouts can span the full display, which works well for visual, immersive interfaces that don’t scroll, as long as nothing conflicts with the Dynamic Island or the status bar. Calculator, for example, occupies the full width of the display. You can also combine both approaches, letting a background image or header span the full width while scrollable content stays inset. The Graphics Content can easily take up the full space which can be achieved by ignoring the safe area (.ignoresSafeArea()). And knowing the iPhone Duo there is no occlusion so I can also ignore the safe area for the interactable content. However we now are entering an awkward state. Because now I need to make decisions based on a specific device. Knowing the iPhone Duo I can ignore horizontal safe area and expand to full width because there is no occlusions here, but ignoring the safe-area may result in unexpected behavior on other (future) devices which then requires me to use code that specificly targets certain devices. I wished SwiftUI had something that I could safely expand the interactable content the full width.
Topic: UI Frameworks SubTopic: SwiftUI
2
0
173
3d
iOS 27.0 crash in UIEditMenuInteraction: BUG_IN_CLIENT_OF_TARGETED_PREVIEW__VIEW_IS_NOT_IN_A_WINDOW
We are seeing an intermittent production crash on iOS 27.0 while the system text-editing menu is active. Environment Device: iPhone 15 OS: iOS 27.0 Orientation: Portrait Xcode: [Xcode 26.4] Detail: Fatal Exception: NSInternalInconsistencyException 0 CoreFoundation 0x98190 __exceptionPreprocess 1 libobjc.A.dylib 0xc380 objc_exception_throw 2 Foundation 0x426ae0 -[NSMutableDictionary(NSMutableDictionary) initWithContentsOfFile:] 3 UIKitCore 0xca4e48 BUG_IN_CLIENT_OF_TARGETED_PREVIEW__VIEW_IS_NOT_IN_A_WINDOW 4 UIKitCore 0x66f558 -[UITargetedPreview initWithView:parameters:] 5 UIKitCore 0x1699cb0 -[UIEditMenuInteraction _contextMenuInteraction:configurationForMenuAtLocation:completion:] 6 UIKitCore 0x174cff8 -[UIContextMenuInteraction _interactionShouldBeginAtPoint:completion:] 7 UIKitCore 0x174a48c -[UIContextMenuInteraction _presentMenuAtLocation3D:] 8 UIKitCore 0x16999a8 -[UIEditMenuInteraction _editMenuPresentation:handoffDisplayedMenuWithContext:] 9 UIKitCore 0x15bf75c -[_UIEditMenuContentPresentation _performContextMenuHandoffForMenu:sourceView:] 10 UIKitCore 0x15bf610 -[_UIEditMenuContentPresentation editMenuListViewDidActivateHandoff:source:] 11 UIKitCore 0xd52810 -[_UIEditMenuListView _performHandoffFromSourceView:] 12 UIKitCore 0x5740c4 -[UIApplication sendAction:to:from:forEvent:] 13 UIKitCore 0x573ef4 -[UIControl sendAction:to:forEvent:] 14 UIKitCore 0x5737f8 -[UIControl _sendActionsForEvents:withEvent:] 15 UIKitCore 0x6d1e94 -[UIButton _sendActionsForEvents:withEvent:] 16 UIKitCore 0xd53bb8 -[_UIEditMenuListView _selectItemAtIndexPath:] 17 UIKitCore 0xd53104 -[_UIEditMenuListView _handleSelectionGesture:] 18 UIKitCore 0x5e798c -[UIGestureRecognizerTarget _sendActionWithGestureRecognizer:] 19 UIKitCore 0x5e77fc _UIGestureRecognizerSendTargetActions 20 UIKitCore 0x5e7580 _UIGestureRecognizerSendActions 21 UIKitCore 0xe4b30 -[UIGestureRecognizer _updateGestureForActiveEvents] 22 UIKitCore 0xe4984 -[UIGestureRecognizer gestureNode:didUpdatePhase:] 23 Gestures 0xcdac __swift_memcpy8_8 24 Gestures 0x397acc block_destroy_helper.6 25 Gestures 0xd514 __swift_memcpy8_8 26 Gestures 0xa87c __swift_memcpy8_8 27 Gestures 0x1a608 __swift_closure_destructor.8 28 UIKitCore 0xea41c -[UIGestureEnvironment _updateForEvent:window:] 29 UIKitCore 0xec298 -[UIWindow sendEvent:] 30 UIKitCore 0x5e5874 -[UIApplication sendEvent:] 31 UIKitCore 0xe2bdc __dispatchPreprocessedEventFromEventQueue 32 UIKitCore 0x6ad78 updateCycleEntry 33 UIKitCore 0x69b88 _UIUpdateSequenceRunNext 34 UIKitCore 0x69928 schedulerStepScheduledMainSectionContinue 35 UpdateCycle 0xbc0 UC::DriverCore::continueProcessing() 36 CoreFoundation 0x267cc __CFMachPortPerform 37 CoreFoundation 0x4a24c CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION 38 CoreFoundation 0x4a45c __CFRunLoopDoSource1 39 CoreFoundation 0x3a634 __CFRunLoopRun 40 CoreFoundation 0x3b7f4 _CFRunLoopRunSpecificWithOptions 41 GraphicsServices 0xf24 GSEventRunModal 42 UIKitCore 0xba1cc UIApplicationMain 43 flashexpress 0x303948 main + 17 (AppDelegate.swift:17) 44 ??? 0x1810675b8 (缺失)
Topic: UI Frameworks SubTopic: UIKit
1
0
64
3d
viewDidDisappear is not called on a popped view controller when switching tabs during UITabBarController's reselect pop-to-root on iOS 27
Issue Description Hi, I would like to share an issue with UIViewController's appearance callbacks inside UITabBarController + UINavigationController on iOS 27. When a tab containing a UINavigationController with two view controllers is re-tapped, UIKit starts its built-in animated pop-to-root. On iOS 27, if the user switches to another tab while that pop animation is still in flight, the popped view controller receives viewWillDisappear: (with isMovingFromParent == true), but viewDidDisappear: is never called on it. The appearance callbacks stay unbalanced. This breaks code that relies on viewDidDisappear: + isMovingFromParent to detect that a view controller was popped. Steps to Reproduce Create a UITabBarController with two tabs. The first tab is a UINavigationController. In the first tab, push a second view controller ("Nested"). Tap the first tab item again. UIKit starts the animated pop-to-root. Immediately (while the pop animation is still running), tap the second tab item. Expected vs. Actual Behavior Expected: On iOS 26, "Nested" receives viewWillDisappear: and then viewDidDisappear:, both with isMovingFromParent == true. Actual: On iOS 27, "Nested" receives only viewWillDisappear:. viewDidDisappear: is NOT called, even though "Nested" is no longer in navigationController.viewControllers. Note: On iOS 27, if the second tab is tapped after the pop animation has finished, viewDidDisappear: is delivered correctly. The issue only occurs when the tab switch happens during the pop transition. Environment Xcode Version 27.0 iOS 27.0 iPhone 18 Pro simulator: reproduces iOS 26.0 iPhone 17 Pro simulator: does not reproduce Feedback Assistant Report ID: FB24934469 Minimal Reproduction Example // SceneDelegate.swift import UIKit class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = scene as? UIWindowScene else { return } let window = UIWindow(windowScene: windowScene) window.rootViewController = TabBarController() window.makeKeyAndVisible() self.window = window } } // TabBarController.swift import UIKit final class TabBarController: UITabBarController { override func viewDidLoad() { super.viewDidLoad() let firstNav = UINavigationController(rootViewController: HomeViewController()) firstNav.tabBarItem = UITabBarItem(title: "First", image: UIImage(systemName: "house"), tag: 0) let second = LoggingViewController(name: "Second") second.tabBarItem = UITabBarItem(title: "Second", image: UIImage(systemName: "star"), tag: 1) viewControllers = [firstNav, second] } } class LoggingViewController: UIViewController { let name: String init(name: String) { self.name = name super.init(nibName: nil, bundle: nil) title = name } required init?(coder: NSCoder) { fatalError() } override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .systemBackground } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) print("[\(name)] viewWillDisappear isMovingFromParent=\(isMovingFromParent)") } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) print("[\(name)] viewDidDisappear isMovingFromParent=\(isMovingFromParent)") } } final class HomeViewController: LoggingViewController { init() { super.init(name: "Home") } required init?(coder: NSCoder) { fatalError() } override func viewDidLoad() { super.viewDidLoad() navigationItem.rightBarButtonItem = UIBarButtonItem( title: "Push", primaryAction: UIAction { [weak self] _ in self?.navigationController?.pushViewController(LoggingViewController(name: "Nested"), animated: true) } ) } }
Topic: UI Frameworks SubTopic: UIKit
0
0
50
4d
Repeated Swift error breakpoint stops in system frameworks during AppKit startup and window creation
I debug an Objective-C++ AppKit application in CLion. The application runs normally, but a “When any is thrown” breakpoint stops repeatedly during startup and window creation, making it difficult to debug. One stop occurs before any window is created: [NSApplication run] → finishLaunching → _customizeMainMenu → [NSTextView _supportsWritingTools] → GenerativeModels → JSONDecoder → swift_willThrow. LLDB identifies a decoding frame as GenerativeModels.AvailabilityStore.ReadinessEntry.Criteria.init(from:). Other stops occur while NSDocumentController attempts to reopen documents, and while AppKit resets gesture recognizers during NSWindow creation. All the supplied stops reach swift_willThrow; the app continues after resuming. Are these expected handled errors? Is there a supported way to prevent the startup Writing Tools check from throwing? I can provide the complete stacks and a minimal reproduction if helpful. I'm on MacOS Tahoe 26.6.2 (25G83) Xcode 26.4.1 - Build version 17E202 Apple clang version 21.0.0 (clang-2100.0.123.102) I'm building from within CLion 2026.2.3 and using the bundled LLDB (21.1.7), but the problem also occurs when using the one from XCode (21.0) Disabling Apple Intelligence in the OS settings does not help.
Topic: UI Frameworks SubTopic: AppKit
0
0
34
4d
CALayer with valid contents and correct configuration is excluded from window compositing on Apple Silicon (works fine on Intel)
macOS/Hardware details: macOS version: 27.0 (build 26A428) Hardware: Apple Silicon Mac (arm64) App architecture: Native arm64 Xcode/SDK: Built against MacOSX27.0 SDK Deployment target: MACOSX_DEPLOYMENT_TARGET = 26.0 Regression history: Same app/codebase previously built and ran correctly on macOS 13 (Ventura), Intel — issue only appears after migrating the build to Apple Silicon; no changes were made to the affected view's drawing or layer-configuration code between the two builds We have a custom, layer-backed NSView (part of a hand-rolled tree/list control that draws its own content via Core Graphics into the layer's contents) that renders completely blank on screen on Apple Silicon Macs, while an adjacent sibling view using the identical view class, drawing code, and layer configuration renders correctly. Using lldb and Xcode's View Debugger against the live process, we've confirmed: The layer's actual backing content is correct: capturing it directly via -renderInContext: produces the expected fully-drawn image (text and icons all present). Every inspectable property of the broken view/layer (hidden, alphaValue, opaque, wantsLayer, isFlipped/isGeometryFlipped, zPosition, masksToBounds, contentsScale, mask, transform, backgroundColor, contents, sublayers, superlayer) is identical to the working sibling view — no configuration difference exists anywhere. The layer's superlayer link is intact and points to the correct parent, ruling out a detached/orphaned layer. Standard remediation attempts — setNeedsDisplay:, displayIfNeeded, toggling wantsLayer, detaching/reattaching the view from its superview, changing zPosition — all have zero effect. Most notably, directly setting layer.backgroundColor to an opaque solid color on the live, correctly-connected layer (verified via property readback) produces no visible change on screen at all. Because even an unconditional background color change is not reflected, the layer appears to be excluded from what's actually sent to the window server for compositing, rather than simply failing to draw updated content. Since all inspectable state is correct and identical to a working sibling view, we've been unable to identify any application-level cause. The view remains fully interactive — clicks and hit-testing resolve correctly to the right underlying data — only the visual output is missing. Are there known Apple Silicon-specific changes to CALayer/NSView compositing (window server layer inclusion, contentsScale/backing-store allocation, or layer-backed view promotion) that could cause a fully valid, connected CALayer with correct contents to be silently dropped from the composited frame? Any suggestions for further diagnostic tools (e.g. Quartz Debug, CARenderServer logging, or WindowServer compositing traces) to narrow this down further would help.
Topic: UI Frameworks SubTopic: AppKit
0
0
16
4d
SplitViewController removed the ability to have a side menu on iPhone
Sometime pre-iOS 26 it was possible to use a SplitViewController so that on iPhone you saw the master as a side menu (e.g. hamburger), and the detail full screen. While on iPad you would see the master displayed in a sidebar that could be closed, with the detail fullscreen. This has changed, using a SplitViewController on iPhone now forces you into having 2 fullscreen screens, with a push/pop layout and a back button. In situations where you want the detail screen to open first, this results in users opening the app to find a back button already presented, despite having not navigated anywhere. They must "return" to a screen they never saw. I really despise this layout and find it to be quite a UX issue. But given the new iPhone Duo, using the SplitViewController is now one of the easiest ways to maintain the necessary responsiveness needed, forcing us to accept this behaviour on regular iPhones. Can we PLEASE get the old functionality back, where we can explicitly state on iPhone that the master will always be displayed as a menu?
0
0
81
4d
App Intents and the Document App Xcode Template
I’m working on an app that deals with a list of text items, so I started with the document app template in Xcode. I have the app basically doing what I want it to do, but I want to be a good ecosystem citizen, so I’d like to conform to app intents. I think that app intents will able to do what I want - accepting text and passing it back out - but I can’t figure out how to access the document outside of my content view and associated subviews. Any guidance would be appreciated. Thank you, Don Carlile
1
0
416
4d
iOS 27: ScrollViewProxy.scrollTo no longer reaches unrealized LazyVStack rows; how to preserve position when prepending?
I have a chat screen built with ScrollView { LazyVStack } and ScrollViewReader. Two things that worked through iOS 26 stopped working on iOS 27 (Xcode 27, iOS 27.0 simulator and device; unchanged code still works on the iOS 26.x simulator): Open at the newest message. On appear I call proxy.scrollTo(lastId, anchor: .bottom). On iOS 27 the list stops two or three rows above the bottom when the rows have variable heights (text bubbles mixed with 200pt images). Load older messages at the top without the list jumping. When the user reaches the top, I prepend 25 older messages and call proxy.scrollTo(previousTopId, anchor: .top) so the row they were reading stays put. On iOS 27 the call does nothing: the list stays at the top of the newly inserted page (offset stays at 0), which immediately re-triggers the load. Re-issuing scrollTo on every layout change for a short window (which is what made this reliable on iOS 26) has no effect on iOS 27. Minimal reproduction import SwiftUI struct Message: Identifiable, Hashable { let id: Int let height: CGFloat // simulates text vs. image bubbles } @MainActor final class ChatModel: ObservableObject { @Published var messages: [Message] = [] @Published var previousTopId: Int? // set when a page is prepended private var nextOldId = 1_000 init() { messages = (0..<25).map { Message(id: nextOldId - $0, height: Self.randomHeight()) }.reversed() nextOldId -= 25 } func loadOlder() { let top = messages.first!.id let page = (0..<25).map { Message(id: nextOldId - $0, height: Self.randomHeight()) }.reversed() nextOldId -= 25 messages.insert(contentsOf: page, at: 0) previousTopId = top // "keep this row at the top" } static func randomHeight() -> CGFloat { [44, 60, 90, 200, 260].randomElement()! } } struct ChatView: View { @StateObject private var model = ChatModel() var body: some View { ScrollViewReader { proxy in ScrollView { LazyVStack(spacing: 8) { // top sentinel: load older when it becomes visible Color.clear.frame(height: 1) .onAppear { model.loadOlder() } ForEach(model.messages) { m in RoundedRectangle(cornerRadius: 12) .fill(m.height >= 200 ? .orange.opacity(0.4) : .blue.opacity(0.3)) .frame(height: m.height) .overlay(Text("\(m.id)")) .padding(.horizontal) .id(m.id) } } } .onAppear { // (1) open at the newest message DispatchQueue.main.async { proxy.scrollTo(model.messages.last!.id, anchor: .bottom) } } .onChange(of: model.previousTopId) { _, id in // (2) restore the row that was at the top before the prepend guard let id else { return } DispatchQueue.main.async { var t = Transaction(); t.disablesAnimations = true withTransaction(t) { proxy.scrollTo(id, anchor: .top) } } } } } } Observed (1) Open at the newest message, scrollTo(lastId, anchor: .bottom) iOS 26.x: lands on the last row. iOS 27.0: stops 2–3 rows above the bottom. (2) Prepend 25 rows, then scrollTo(previousTopId, anchor: .top) iOS 26.x: the previous top row is at the top of the viewport. iOS 27.0: the offset stays at 0 and the new page's first row is at the top. What I have tried on iOS 27 Re-issuing scrollTo for 0.5s on every content-height or offset change (via GeometryReader preferences). No effect; the target row is not realized, and the visible rows are kept stable instead. .defaultScrollAnchor(.bottom) and .defaultScrollAnchor(.bottom, for: .sizeChanges): fixes the initial open, but the stored anchor is re-applied once on the first content change (the prepend), which snaps the list to the newest message. .sizeChanges did not preserve the prepend. .scrollPosition(id: $topId, anchor: .top) with .scrollTargetLayout() on the LazyVStack: the binding tracks the top row correctly, but after the prepend SwiftUI re-targets the binding to the new page's first row. Writing the previous id back, in the same update or on later run-loop turns, does not restore the position. Replacing LazyVStack with VStack fixes both cases, but the list holds hundreds of image rows and needs the lazy container for memory. What does work: reaching the backing UIScrollView (SwiftUIIntrospect), recording the visible rows' frames before the insert and adjusting contentOffset after layout. It works but is a lot of code for something that used to be one scrollTo. Questions Is it intended on iOS 27 that ScrollViewProxy.scrollTo does not scroll to a LazyVStack row that is not currently realized, or that the lazy stack keeps the currently visible rows stable in preference to the requested target? The WWDC26 lazy-stacks session describes the stack and scroll view coordinating the offset as estimates update; is scrollTo to an unrealized row now unsupported? Is there a supported SwiftUI way on iOS 27 to keep the visible rows in place when items are prepended to a LazyVStack, or to scroll reliably to an unrealized row? For example a ScrollPosition usage or an anchor role I am missing. If not, is adjusting the UIScrollView offset the expected approach, or is List now the recommended container for chat-style lists with bidirectional paging? I have filed this as FB24968838 with the sample project attached.
Replies
0
Boosts
0
Views
56
Activity
1d
iOS 27: swipeActions outside List never re-evaluates its content closure (stale labels, if gating ignored) — intended?
We are adopting the iOS 27 support for swipeActions on rows inside a ScrollView { LazyVStack } (with swipeActionsContainer() on the scroll view). We expected the row modifier to behave like it does inside List, but on iOS 27.0 (24A437, iPhone 17; also 27.0 simulator) the content closure appears to be evaluated only once, when the row is first registered, and never again while the row stays on screen. Is this the intended behavior, or a bug? What we observe Stale button labels / actions. A button whose title depends on state (Button(isPinned ? "Unpin" : "Pin")) keeps its first title after the state changes. The row body itself re-renders with the new state, but the swipe actions do not, until the row is recycled by the lazy stack (scroll it off-screen and back) — then it shows the new value. Conditional content is ignored. swipeActions { if !editing { Button(...) } } keeps showing the buttons after editing becomes true, and the row can still be swiped. Views placed inside the content that observe state themselves (an @Observable/@ObservedObject child view) do update their text. But an if inside that child view does not remove the buttons, and emptying a ForEach inside it removes the buttons while the row still slides open (onPresentationChanged fires with true). onLongPressGesture(minimumDuration: 0.7) on the same row fires only on touch-up (after ~3 s of holding) when the row has swipe actions in a ScrollView; inside List, and in a ScrollView without swipe actions, it fires at ~0.7 s while still pressed. The same row code inside List behaves as expected for all four points. Attaching or omitting swipeActionsContainer() and using the old swipeActions(edge:allowsFullSwipe:content:) overload instead of the new onPresentationChanged overload makes no difference. Minimal reproduction (iOS 27 only, single file) import SwiftUI @Observable final class Model { var editing = false var pinned: Set<Int> = [] } @available(iOS 27, *) struct ContentView: View { @State private var model = Model() @State private var lastLongPress = "-" var body: some View { VStack(spacing: 8) { Toggle("Editing (swipe should be off)", isOn: $model.editing) Text("long press: \(lastLongPress)").font(.caption) ScrollView { LazyVStack(spacing: 0) { ForEach(1...30, id: \.self) { n in HStack { Text("Row \(n)") Spacer() Text(model.pinned.contains(n) ? "pinned" : "").foregroundStyle(.secondary) } .frame(height: 56) .contentShape(Rectangle()) .onLongPressGesture(minimumDuration: 0.7) { lastLongPress = "row \(n) @ \(Date().formatted(date: .omitted, time: .standard))" } .swipeActions(edge: .trailing, allowsFullSwipe: false) { if !model.editing { // (2) ignored after first registration Button(model.pinned.contains(n) ? "Unpin" : "Pin") { // (1) title stays "Pin" if model.pinned.contains(n) { model.pinned.remove(n) } else { model.pinned.insert(n) } } .tint(.blue) } } onPresentationChanged: { _ in } } } } .swipeActionsContainer() } .padding(.horizontal) } } Steps: Swipe row 3, tap Pin. The row shows "pinned". Swipe row 3 again → the button still says Pin (in List it says Unpin). Tapping it runs the closure with the current model, so it unpins, but the label was wrong. Turn Editing on, swipe any row → it still opens with the button (in List it does not open). Press and hold a row for 3 s → "long press" timestamp is written only when the finger lifts. Questions Is "evaluate the swipeActions content once per row registration" the intended contract for swipe actions outside List? The documentation for swipeActionsContainer() only describes coordination (single open row, dismiss on scroll / outside tap), and swipeActions(edge:allowsFullSwipe:content:) doesn't mention any difference between List and other containers. If it is intended, what is the recommended way to (a) disable swipe for a row temporarily (e.g. during an edit mode) and (b) update button titles from state, without recreating the row view? We currently work around it with a child view that observes the model for titles, and allowsHitTesting(false) on the row to disable swiping, but both feel like they rely on undocumented behavior. Is the delayed onLongPressGesture (fires on touch-up) expected when a row carries swipe actions in a ScrollView? simultaneousGesture(LongPressGesture(...)) fires while pressed, which suggests the swipe recognizer imposes a failure requirement on the row's gestures.
Replies
0
Boosts
0
Views
55
Activity
1d
Honored Interface Orientations on the iPhone Duo Inner Display
Hello, In Apple’s Tech Talk Prepare your app for iPhone Duo, Apple mentions that on the Duo internal display, supported interface orientations are not honored unless UIRequiresFullScreen is enabled, in which case the app is scaled. I first tested the behavior described by Apple. With UIRequiresFullScreen enabled, I returned .portrait from UIWindowSceneDelegate.supportedInterfaceOrientations(for:), added only UIInterfaceOrientationPortrait in Info.plist, and the app remained upright, using letterboxing as needed, which matched Apple’s description. However, if I add all interface orientations in Info.plist while the scene delegate still returns .portrait, the app becomes fullscreen and locked in portrait orientation, like a portrait-only app, which seems to diverge significantly from the behavior described in the Tech Talk. I then tested most possible combinations and observed five distinct behaviors: Normal: Auto-rotated, always fullscreen B-Portrait: Auto-rotated, fullscreen in portrait; portrait letterboxed in landscape B-Landscape: Auto-rotated, fullscreen in landscape; landscape letterboxed in portrait L-Portrait: Locked in portrait L-Landscape: Locked in landscape But no rule seems to explain how a given combination determines the resulting behavior. Not even AI could figure out a sane one. Does anyone have any idea how this works?
Topic: UI Frameworks SubTopic: UIKit
Replies
0
Boosts
0
Views
38
Activity
1d
Charts are broken with Xcode 27, Plotting multiple lines
Hi, Charts—specifically those with multiple lines—are broken in Xcode 27. First, I spotted the bug in my program, and then I checked your example. Your own example Plotting-multiple-lines is not working correctly anymore. It shows 1 line or sometimes no lines at all, depending on the order of the data. It depends on how the data is passed to the chart. If the data is passed as separate series, it works. In Visualizing your app’s data it works, but the data is passed as described before. Don't follow Microslop: have the AI ​​generate the code and then skip the tests. This is a serious bug that requires a lot of work to rearrange the data, just to work around the issue. Christian
Replies
2
Boosts
0
Views
247
Activity
1d
UINavigationBarAppearance background does not extend to the top edge on iPhone Duo
Environment Xcode 27.1 iOS 27.1 iPhone Duo simulator UIKit app built with the iOS 27.1 SDK Issue On iPhone Duo, the background of a system-managed UINavigationBar does not extend completely to the top edge of the window. The navigation bar is configured using UINavigationBarAppearance with an opaque blue background. However, a horizontal white strip remains above the blue navigation bar. I also post a feedback: FB24859353 Questions Is this expected behavior on iPhone Duo? What is the recommended way to style this top region? Should apps add a custom background underlay outside the UINavigationBar bounds? Could this be an iOS 27.1 or iPhone Duo simulator issue? Minimal reproduction code: import UIKit final class DemoTabBarController: UITabBarController { override func viewDidLoad() { super.viewDidLoad() viewControllers = NavigationBarStyle.allCases.map { style in let content = DiagnosticsViewController(style: style) let navigationController = UINavigationController(rootViewController: content) navigationController.tabBarItem = UITabBarItem( title: style.title, image: UIImage(systemName: style.symbolName), selectedImage: nil ) style.apply(to: navigationController.navigationBar) return navigationController } } } enum NavigationBarStyle: CaseIterable { case systemDefault case appearance case legacy var title: String { switch self { case .systemDefault: return "Default" case .appearance: return "Appearance" case .legacy: return "Legacy" } } var symbolName: String { switch self { case .systemDefault: return "iphone" case .appearance: return "paintbrush" case .legacy: return "clock.arrow.circlepath" } } func apply(to navigationBar: UINavigationBar) { switch self { case .systemDefault: break case .appearance: let appearance = UINavigationBarAppearance() appearance.configureWithOpaqueBackground() appearance.backgroundColor = .demoBlue appearance.shadowColor = nil appearance.titleTextAttributes = [.foregroundColor: UIColor.white] navigationBar.tintColor = .white navigationBar.standardAppearance = appearance navigationBar.compactAppearance = appearance navigationBar.scrollEdgeAppearance = appearance case .legacy: navigationBar.tintColor = .white navigationBar.barTintColor = .demoBlue navigationBar.backgroundColor = .demoBlue navigationBar.setBackgroundImage(Self.solidImage(color: .demoBlue), for: .default) navigationBar.shadowImage = UIImage() navigationBar.isTranslucent = false navigationBar.titleTextAttributes = [.foregroundColor: UIColor.white] } } private static func solidImage(color: UIColor) -> UIImage { return UIGraphicsImageRenderer(size: CGSize(width: 1, height: 1)).image { context in color.setFill() context.fill(CGRect(x: 0, y: 0, width: 1, height: 1)) } } } private extension UIColor { static let demoBlue = UIColor(red: 0.0, green: 0.46, blue: 0.70, alpha: 1.0) }
Replies
2
Boosts
1
Views
292
Activity
1d
Content Not using Available Space In UICollectionViewListCell in iPhone Duo
Instead of centering the content within the available cell space, the content is to the left of center in an iPhone Duo simulation. The content is fine in an iPhone Pro simulation.
Replies
1
Boosts
0
Views
350
Activity
2d
How to Keep Out a Tinted navigationbar from the Combined Status Bar Region in iPhone Duo using Swiftui
I think the title says it all.
Replies
1
Boosts
0
Views
329
Activity
2d
Can a Notes note be dragged into another app on iPhone Duo?
I’m adding drag-and-drop support to my app for multitasking on iPhone Duo. My app supports text/note content. Currently, a user can move content from Apple Notes into my app using Share or Copy/Paste. ** Questions** Can a note from the Notes app be dragged directly into another app during multitasking, similar to dragging a photo? If so, what content type does Notes provide through the drag-and-drop session? For example, is the note exposed as plain text (public.plain-text / UTType.plainText), rich text, or another transferable type? My goal is for the user to drag a note from Notes into my app and have it behave essentially like Copy → Paste, without requiring the Share sheet. Thank you.
Replies
0
Boosts
0
Views
76
Activity
2d
SwiftUI Document API Duplicate Function hangs on macOS 27
In a macOS 27 app using DocumentGroup(editor:makeDocument:) with a type conforming to the new Document protocol, choosing File › Duplicate hangs the app permanently (0% CPU, spinning beach ball, must force quit). The main thread is blocked in URLPlatformDocument.read(from:ofType:) waiting on a dispatch semaphore. That synchronous NSDocument read path is reached from NSDocumentController.duplicateDocumentWithContentsOfURL(:copying:displayName:) → makeDocumentForURL(:withContentsOf:ofType:) → NSDocument.init(for:withContentsOf:ofType:). The work the semaphore waits for never runs: the app's makeDocument closure is never called. The SDK declares makeDocument and ReadableDocument.apply(snapshot:previous:) as @MainActor, so blocking the main thread while waiting for them can never complete. This reproduces with Apple's unmodified sample code project "Building a Document-Based App with SwiftUI" (no code or project changes; only a signing team set). Our own app, which uses a custom DocumentReader/DocumentWriter with Source/Destination == URL, hangs with the identical stack. Has anyone found any workaround? Filed Feedback FB24949862
Topic: UI Frameworks SubTopic: SwiftUI
Replies
0
Boosts
0
Views
63
Activity
2d
sidebarAdaptable Design Problem
This is what Apple's Destination Video Sample App looks like on iPhone Duo built with SDK 27.1 beta. Two things: Items that should not appear in the tab bar appear. There is no sidebar for iPhone Duo. So my problem is: is this a bug or a design on purpose? Will sidebarAdaptable gets a sidebar on iPhone Duo? Or at least, how to hide these things that should only appear in the sidebar? The sample app uses .defaultVisibility(, for:) and .hidden() but obviously none of these takes effect.
Topic: UI Frameworks SubTopic: SwiftUI
Replies
1
Boosts
1
Views
186
Activity
2d
How to check for multiple scene support on iPhone Duo?
I have an iOS app that supports multiple scenes on the iPad, and which has an "Open in Another Window" feature which creates a new window scene. I would like to bring this feature to the iPhone Duo. On the iPhone Duo, of course, creating new windows is only supported when the device is open; when it is closed, creating new windows does not work. (If you try, an error is thrown.) Until now, the way I have checked whether my "Open in Another Window" feature should be available is to check to see if UIApplication.shared.supportsMultipleScenes is true. This has always returned false for previous iPhones and true for iPads. Unfortunately, however, this does not work as expected on the iPhone Duo. On the Duo, I would expect supportsMultipleScenes to return true when the device is open, but false when it is closed. This is not the case: it returns true for all poses. (Filed as #FB24948411 as this doesn't seem right to me.) So it does not help me decide whether the feature should be available. UIWindowScene.ActivationAction does work as expected when used in a menu, with the action auto-hiding when the Duo is in the closed pose. In my app, though, I need more than just an auto-hiding menu item; I need to check whether creating a new window is currently possible for certain UI availability decisions. What, then, is the correct way of checking this, if it's not with supportsMultipleScenes? Given that UIWindowScene.ActivationAction is able to hide itself, I assume there is some better way of checking that I have missed.
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
0
Boosts
0
Views
70
Activity
2d
Supported way to put an iPhone Duo simulator into the unfolded state programmatically
The Duo simulator boots showing only the outer display: the window is fixed at 382×644 pt and our layout classifier always reports the compact stack mode. We measured this on two separate clean boots (shutdown, erase, boot). xcrun simctl help lists no subcommand for folding, posture, or selecting the inner display — we read the full list. xcrun simctl io screenshot does reveal a second display (LCD-1, 2007×2853 px, aspect 0.70, close to the 669×951 inner portrait size). Unfolding manually in the Simulator UI works and the app then renders the two-column layout correctly, but we could not find a programmatic equivalent. Is there a supported way to unfold a Duo simulator from the command line or from XCTest?
Topic: UI Frameworks SubTopic: SwiftUI
Replies
3
Boosts
3
Views
751
Activity
3d
Enable iPhone Duo Upside Down Orientation
Ever since the iPhone X, upside-down orientation on the iPhone has been disabled by design. I haven't found any official documentation explaining why, but my guess is it has to do with Face ID and the top notch. However, now that the iPhone Duo has no Face ID or notch—and includes reserved occlusion regions—why not enable upside-down rotation? As of iOS 27.1, it remains disabled. Leaving it turned off only confuses users, making them think their favorite apps are frozen when they won't rotate.
Topic: UI Frameworks SubTopic: SwiftUI
Replies
1
Boosts
1
Views
330
Activity
3d
iPhone Duo and the Safe-Area
I took a screenshot of the Safety Area's and Occlusions on the iPhone Duo outer display. The article Designing for iPhone Duo tells us to... Consider using the full display width for interfaces where bars aren’t necessary. Some layouts can span the full display, which works well for visual, immersive interfaces that don’t scroll, as long as nothing conflicts with the Dynamic Island or the status bar. Calculator, for example, occupies the full width of the display. You can also combine both approaches, letting a background image or header span the full width while scrollable content stays inset. The Graphics Content can easily take up the full space which can be achieved by ignoring the safe area (.ignoresSafeArea()). And knowing the iPhone Duo there is no occlusion so I can also ignore the safe area for the interactable content. However we now are entering an awkward state. Because now I need to make decisions based on a specific device. Knowing the iPhone Duo I can ignore horizontal safe area and expand to full width because there is no occlusions here, but ignoring the safe-area may result in unexpected behavior on other (future) devices which then requires me to use code that specificly targets certain devices. I wished SwiftUI had something that I could safely expand the interactable content the full width.
Topic: UI Frameworks SubTopic: SwiftUI
Replies
2
Boosts
0
Views
173
Activity
3d
iOS 27.0 crash in UIEditMenuInteraction: BUG_IN_CLIENT_OF_TARGETED_PREVIEW__VIEW_IS_NOT_IN_A_WINDOW
We are seeing an intermittent production crash on iOS 27.0 while the system text-editing menu is active. Environment Device: iPhone 15 OS: iOS 27.0 Orientation: Portrait Xcode: [Xcode 26.4] Detail: Fatal Exception: NSInternalInconsistencyException 0 CoreFoundation 0x98190 __exceptionPreprocess 1 libobjc.A.dylib 0xc380 objc_exception_throw 2 Foundation 0x426ae0 -[NSMutableDictionary(NSMutableDictionary) initWithContentsOfFile:] 3 UIKitCore 0xca4e48 BUG_IN_CLIENT_OF_TARGETED_PREVIEW__VIEW_IS_NOT_IN_A_WINDOW 4 UIKitCore 0x66f558 -[UITargetedPreview initWithView:parameters:] 5 UIKitCore 0x1699cb0 -[UIEditMenuInteraction _contextMenuInteraction:configurationForMenuAtLocation:completion:] 6 UIKitCore 0x174cff8 -[UIContextMenuInteraction _interactionShouldBeginAtPoint:completion:] 7 UIKitCore 0x174a48c -[UIContextMenuInteraction _presentMenuAtLocation3D:] 8 UIKitCore 0x16999a8 -[UIEditMenuInteraction _editMenuPresentation:handoffDisplayedMenuWithContext:] 9 UIKitCore 0x15bf75c -[_UIEditMenuContentPresentation _performContextMenuHandoffForMenu:sourceView:] 10 UIKitCore 0x15bf610 -[_UIEditMenuContentPresentation editMenuListViewDidActivateHandoff:source:] 11 UIKitCore 0xd52810 -[_UIEditMenuListView _performHandoffFromSourceView:] 12 UIKitCore 0x5740c4 -[UIApplication sendAction:to:from:forEvent:] 13 UIKitCore 0x573ef4 -[UIControl sendAction:to:forEvent:] 14 UIKitCore 0x5737f8 -[UIControl _sendActionsForEvents:withEvent:] 15 UIKitCore 0x6d1e94 -[UIButton _sendActionsForEvents:withEvent:] 16 UIKitCore 0xd53bb8 -[_UIEditMenuListView _selectItemAtIndexPath:] 17 UIKitCore 0xd53104 -[_UIEditMenuListView _handleSelectionGesture:] 18 UIKitCore 0x5e798c -[UIGestureRecognizerTarget _sendActionWithGestureRecognizer:] 19 UIKitCore 0x5e77fc _UIGestureRecognizerSendTargetActions 20 UIKitCore 0x5e7580 _UIGestureRecognizerSendActions 21 UIKitCore 0xe4b30 -[UIGestureRecognizer _updateGestureForActiveEvents] 22 UIKitCore 0xe4984 -[UIGestureRecognizer gestureNode:didUpdatePhase:] 23 Gestures 0xcdac __swift_memcpy8_8 24 Gestures 0x397acc block_destroy_helper.6 25 Gestures 0xd514 __swift_memcpy8_8 26 Gestures 0xa87c __swift_memcpy8_8 27 Gestures 0x1a608 __swift_closure_destructor.8 28 UIKitCore 0xea41c -[UIGestureEnvironment _updateForEvent:window:] 29 UIKitCore 0xec298 -[UIWindow sendEvent:] 30 UIKitCore 0x5e5874 -[UIApplication sendEvent:] 31 UIKitCore 0xe2bdc __dispatchPreprocessedEventFromEventQueue 32 UIKitCore 0x6ad78 updateCycleEntry 33 UIKitCore 0x69b88 _UIUpdateSequenceRunNext 34 UIKitCore 0x69928 schedulerStepScheduledMainSectionContinue 35 UpdateCycle 0xbc0 UC::DriverCore::continueProcessing() 36 CoreFoundation 0x267cc __CFMachPortPerform 37 CoreFoundation 0x4a24c CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION 38 CoreFoundation 0x4a45c __CFRunLoopDoSource1 39 CoreFoundation 0x3a634 __CFRunLoopRun 40 CoreFoundation 0x3b7f4 _CFRunLoopRunSpecificWithOptions 41 GraphicsServices 0xf24 GSEventRunModal 42 UIKitCore 0xba1cc UIApplicationMain 43 flashexpress 0x303948 main + 17 (AppDelegate.swift:17) 44 ??? 0x1810675b8 (缺失)
Topic: UI Frameworks SubTopic: UIKit
Replies
1
Boosts
0
Views
64
Activity
3d
viewDidDisappear is not called on a popped view controller when switching tabs during UITabBarController's reselect pop-to-root on iOS 27
Issue Description Hi, I would like to share an issue with UIViewController's appearance callbacks inside UITabBarController + UINavigationController on iOS 27. When a tab containing a UINavigationController with two view controllers is re-tapped, UIKit starts its built-in animated pop-to-root. On iOS 27, if the user switches to another tab while that pop animation is still in flight, the popped view controller receives viewWillDisappear: (with isMovingFromParent == true), but viewDidDisappear: is never called on it. The appearance callbacks stay unbalanced. This breaks code that relies on viewDidDisappear: + isMovingFromParent to detect that a view controller was popped. Steps to Reproduce Create a UITabBarController with two tabs. The first tab is a UINavigationController. In the first tab, push a second view controller ("Nested"). Tap the first tab item again. UIKit starts the animated pop-to-root. Immediately (while the pop animation is still running), tap the second tab item. Expected vs. Actual Behavior Expected: On iOS 26, "Nested" receives viewWillDisappear: and then viewDidDisappear:, both with isMovingFromParent == true. Actual: On iOS 27, "Nested" receives only viewWillDisappear:. viewDidDisappear: is NOT called, even though "Nested" is no longer in navigationController.viewControllers. Note: On iOS 27, if the second tab is tapped after the pop animation has finished, viewDidDisappear: is delivered correctly. The issue only occurs when the tab switch happens during the pop transition. Environment Xcode Version 27.0 iOS 27.0 iPhone 18 Pro simulator: reproduces iOS 26.0 iPhone 17 Pro simulator: does not reproduce Feedback Assistant Report ID: FB24934469 Minimal Reproduction Example // SceneDelegate.swift import UIKit class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = scene as? UIWindowScene else { return } let window = UIWindow(windowScene: windowScene) window.rootViewController = TabBarController() window.makeKeyAndVisible() self.window = window } } // TabBarController.swift import UIKit final class TabBarController: UITabBarController { override func viewDidLoad() { super.viewDidLoad() let firstNav = UINavigationController(rootViewController: HomeViewController()) firstNav.tabBarItem = UITabBarItem(title: "First", image: UIImage(systemName: "house"), tag: 0) let second = LoggingViewController(name: "Second") second.tabBarItem = UITabBarItem(title: "Second", image: UIImage(systemName: "star"), tag: 1) viewControllers = [firstNav, second] } } class LoggingViewController: UIViewController { let name: String init(name: String) { self.name = name super.init(nibName: nil, bundle: nil) title = name } required init?(coder: NSCoder) { fatalError() } override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .systemBackground } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) print("[\(name)] viewWillDisappear isMovingFromParent=\(isMovingFromParent)") } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) print("[\(name)] viewDidDisappear isMovingFromParent=\(isMovingFromParent)") } } final class HomeViewController: LoggingViewController { init() { super.init(name: "Home") } required init?(coder: NSCoder) { fatalError() } override func viewDidLoad() { super.viewDidLoad() navigationItem.rightBarButtonItem = UIBarButtonItem( title: "Push", primaryAction: UIAction { [weak self] _ in self?.navigationController?.pushViewController(LoggingViewController(name: "Nested"), animated: true) } ) } }
Topic: UI Frameworks SubTopic: UIKit
Replies
0
Boosts
0
Views
50
Activity
4d
Repeated Swift error breakpoint stops in system frameworks during AppKit startup and window creation
I debug an Objective-C++ AppKit application in CLion. The application runs normally, but a “When any is thrown” breakpoint stops repeatedly during startup and window creation, making it difficult to debug. One stop occurs before any window is created: [NSApplication run] → finishLaunching → _customizeMainMenu → [NSTextView _supportsWritingTools] → GenerativeModels → JSONDecoder → swift_willThrow. LLDB identifies a decoding frame as GenerativeModels.AvailabilityStore.ReadinessEntry.Criteria.init(from:). Other stops occur while NSDocumentController attempts to reopen documents, and while AppKit resets gesture recognizers during NSWindow creation. All the supplied stops reach swift_willThrow; the app continues after resuming. Are these expected handled errors? Is there a supported way to prevent the startup Writing Tools check from throwing? I can provide the complete stacks and a minimal reproduction if helpful. I'm on MacOS Tahoe 26.6.2 (25G83) Xcode 26.4.1 - Build version 17E202 Apple clang version 21.0.0 (clang-2100.0.123.102) I'm building from within CLion 2026.2.3 and using the bundled LLDB (21.1.7), but the problem also occurs when using the one from XCode (21.0) Disabling Apple Intelligence in the OS settings does not help.
Topic: UI Frameworks SubTopic: AppKit
Replies
0
Boosts
0
Views
34
Activity
4d
CALayer with valid contents and correct configuration is excluded from window compositing on Apple Silicon (works fine on Intel)
macOS/Hardware details: macOS version: 27.0 (build 26A428) Hardware: Apple Silicon Mac (arm64) App architecture: Native arm64 Xcode/SDK: Built against MacOSX27.0 SDK Deployment target: MACOSX_DEPLOYMENT_TARGET = 26.0 Regression history: Same app/codebase previously built and ran correctly on macOS 13 (Ventura), Intel — issue only appears after migrating the build to Apple Silicon; no changes were made to the affected view's drawing or layer-configuration code between the two builds We have a custom, layer-backed NSView (part of a hand-rolled tree/list control that draws its own content via Core Graphics into the layer's contents) that renders completely blank on screen on Apple Silicon Macs, while an adjacent sibling view using the identical view class, drawing code, and layer configuration renders correctly. Using lldb and Xcode's View Debugger against the live process, we've confirmed: The layer's actual backing content is correct: capturing it directly via -renderInContext: produces the expected fully-drawn image (text and icons all present). Every inspectable property of the broken view/layer (hidden, alphaValue, opaque, wantsLayer, isFlipped/isGeometryFlipped, zPosition, masksToBounds, contentsScale, mask, transform, backgroundColor, contents, sublayers, superlayer) is identical to the working sibling view — no configuration difference exists anywhere. The layer's superlayer link is intact and points to the correct parent, ruling out a detached/orphaned layer. Standard remediation attempts — setNeedsDisplay:, displayIfNeeded, toggling wantsLayer, detaching/reattaching the view from its superview, changing zPosition — all have zero effect. Most notably, directly setting layer.backgroundColor to an opaque solid color on the live, correctly-connected layer (verified via property readback) produces no visible change on screen at all. Because even an unconditional background color change is not reflected, the layer appears to be excluded from what's actually sent to the window server for compositing, rather than simply failing to draw updated content. Since all inspectable state is correct and identical to a working sibling view, we've been unable to identify any application-level cause. The view remains fully interactive — clicks and hit-testing resolve correctly to the right underlying data — only the visual output is missing. Are there known Apple Silicon-specific changes to CALayer/NSView compositing (window server layer inclusion, contentsScale/backing-store allocation, or layer-backed view promotion) that could cause a fully valid, connected CALayer with correct contents to be silently dropped from the composited frame? Any suggestions for further diagnostic tools (e.g. Quartz Debug, CARenderServer logging, or WindowServer compositing traces) to narrow this down further would help.
Topic: UI Frameworks SubTopic: AppKit
Replies
0
Boosts
0
Views
16
Activity
4d
SplitViewController removed the ability to have a side menu on iPhone
Sometime pre-iOS 26 it was possible to use a SplitViewController so that on iPhone you saw the master as a side menu (e.g. hamburger), and the detail full screen. While on iPad you would see the master displayed in a sidebar that could be closed, with the detail fullscreen. This has changed, using a SplitViewController on iPhone now forces you into having 2 fullscreen screens, with a push/pop layout and a back button. In situations where you want the detail screen to open first, this results in users opening the app to find a back button already presented, despite having not navigated anywhere. They must "return" to a screen they never saw. I really despise this layout and find it to be quite a UX issue. But given the new iPhone Duo, using the SplitViewController is now one of the easiest ways to maintain the necessary responsiveness needed, forcing us to accept this behaviour on regular iPhones. Can we PLEASE get the old functionality back, where we can explicitly state on iPhone that the master will always be displayed as a menu?
Replies
0
Boosts
0
Views
81
Activity
4d
App Intents and the Document App Xcode Template
I’m working on an app that deals with a list of text items, so I started with the document app template in Xcode. I have the app basically doing what I want it to do, but I want to be a good ecosystem citizen, so I’d like to conform to app intents. I think that app intents will able to do what I want - accepting text and passing it back out - but I can’t figure out how to access the document outside of my content view and associated subviews. Any guidance would be appreciated. Thank you, Don Carlile
Replies
1
Boosts
0
Views
416
Activity
4d