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
1.5k
5d
Show onboarding steps side by side on iPhone Duo
Hi, I'm currently in the process of updating my app, which only supports iPhone at the moment, and I'm wondering how I could update my onboarding flow to take advantage of the iPhone Duo when unfolded. Basically the onboarding is a succession of screens, all presented inside a NavigationStack one after the other. I had the idea of using all the screen area to show those screens 2 by 2 (side by side). At first I thought about using NavigationSplitView to accomplish this (pairs of them) but I couldn't get a 50/50 ratio and it felt more of a hack. I then turned my attention to ArrangementView using an horizontal split but in certain layouts only the primary is shown and I'm not sure how I can detect that to show the secondary on push. Would anybody know what the best way would be to accomplish this? Or is it not a good idea at all? Thanks!
Topic: UI Frameworks SubTopic: SwiftUI
0
0
15
1h
iPadOS 27.0.1: iPhone-only apps crash when displaying the Japanese Kana keyboard on iPad
We are seeing a crash when attempting to display the Japanese Kana keyboard (日本語-かな) in our iPhone-only app running on an iPad with iPadOS 27.0.1. The keyboard displays successfully in our app on iPadOS 26 and iPadOS 27.0. We also reproduced a similar crash in other iPhone-only apps downloaded from the App Store on the affected iPad. We have not yet confirmed whether those apps crash with the same exception. Our app logs the following exception: *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM insertObject:atIndex:]: index 15 beyond bounds [0 .. 2]' *** First throw call stack: ( 0x19fab7190 0x19f834380 0x19fa45734 0x1aee9f5bc 0x1aee3dc14 0x1aee3cb30 0x1aee3c4d4 0x1aee3ab0c 0x1a433798c 0x1a44a4120 0x1a449bd5c 0x1a42148c8 0x1a42143fc 0x1a4239d7c 0x1a421203c 0x1a3fc1338 0x1a3d12e0c 0x1a3d11ed0 0x1a52784ec 0x1a3d11abc 0x1a4115238 0x1a3d436d4 0x1a3d43a80 0x1a44eea14 0x1aabb8ef8 0x1a517161c 0x1a5152450 0x1a5153388 0x1a41f20c4 0x1a49e3fec 0x1a426598c 0x1a42657fc 0x1a4265580 0x1a3d62b30 0x1a3d62984 0x1a95c4dac 0x1a994fb68 0x1a95c5514 0x1a95c287c 0x1a95d2608 0x1a3d6841c 0x1a3d6a298 0x1a4263874 0x1a3d60bdc 0x1a3ce8d78 0x1a3ce7b88 0x1a3ce7928 0x2d1482bc0 0x19fa78c20 0x19fa78b94 0x19fa5a268 0x19fa59384 0x19fa5a7f4 0x249e6ff24 0x1a3d381cc 0x1a9d27404 0x1a9d20b50 0x1a9d20a10 0x109042dc4 0x109042e04 0x19f8ab5b8 ) libc++abi: terminating due to uncaught exception of type NSException Steps to reproduce: Enable the Japanese – Kana keyboard in the iPad’s keyboard settings. Open an affected iPhone-only app on an iPad running iPadOS 27.0.1. Tap a text input field and attempt to display the Japanese Kana keyboard. The app crashes. We suspect this may be a regression involving iPhone compatibility mode on iPad and the Japanese Kana keyboard, but we have not yet identified the failing component in a symbolicated stack trace. We have submitted a report through Feedback Assistant: FB24985530. Has anyone else encountered this behavior? Are there any known workarounds we can apply in the app while this is being investigated?
Topic: UI Frameworks SubTopic: UIKit Tags:
0
0
24
1h
Sandboxed macOS dictation: insert at the current focused input across apps
Update: I clarified the intended behavior after posting. The destination is the text input that has keyboard focus when the finished dictation is delivered, even if the user changed fields or apps while speaking. We do not need to return to the field where dictation started. I’m building a macOS dictation app for the Mac App Store, so it must run with App Sandbox enabled. For example, a user might start dictating with an input in Chrome focused, then click into a ChatGPT input while speaking. When the result is ready, it should insert at the ChatGPT caret. Moving the caret within one app should likewise change the destination. In an isolated signed sandboxed prototype, I write a marker to the general pasteboard and post Command–V with CGEvent.post after the user grants event-posting access. This inserts successfully in TextEdit at the current caret, including after a same-document caret move. That result is now consistent with the intended behavior. The prototype also has a frontmost-process guard that withholds insertion after an app switch; that is our own guard and could be removed. We have not yet verified cross-app delivery without it. The existing nonsandboxed app uses AXUIElement to inspect the focused field. Apple’s App Sandbox documentation lists assistive Accessibility APIs as incompatible with sandboxed apps. For a current-focus insertion design, is there any supported sandbox-compatible way to know whether the destination has a focused editable field or is a secure input, or to learn whether a posted paste was actually accepted? If not, is relying on the destination app’s paste handling and retaining the transcript for manual recovery the expected approach? I also tested an AppKit Service. TextEdit inserts its returned text when the caret stays put; after a physical click to another caret during a pending request, the provider returns but TextEdit inserts nothing. This does not appear to fit our hold-to-dictate, switch-apps-while-speaking interaction. I’d welcome experience with another system-mediated approach that does. Environment: macOS 27.0, Xcode 27.0, Apple Silicon. I’m asking about technical API behavior and implementation patterns, not a guarantee of App Review approval.
1
0
236
5h
Unexpected sceneDidBecomeActive called during screen lock in iOS 27
I've noticed a strange issue with the SceneDelegate lifecycle in iOS 27. [Environment] iOS 27 (Also tested on physical devices) UIKit / SceneDelegate based App [Description & Steps to Reproduce] When the app is in the foreground and the user locks the screen (presses the power button): In iOS 26 and earlier: sceneWillResignActive is called exactly once. (Expected behavior) In iOS 27: The following sequence is called rapidly in succession: sceneWillResignActive (Screen lock initiated) sceneDidBecomeActive sceneWillResignActive (Locks completely) When the user unlocks the screen later, sceneDidBecomeActive is called once as usual. [Impact] Because sceneDidBecomeActive is unexpectedly fired while the device is locking, it triggers foreground logics right before the app is pushed to the background. This is causing unwanted side-effects and glitches. Has anyone else encountered this unbalanced lifecycle issue in iOS 27? I'd like to know if there's a better approach or if Apple is aware of this. Thanks!
1
1
51
7h
iPhone duo toolbar items misplaced for inspector view
I am displaying the same view via a push onto the secondary view of a modern uisplitviewcontroller and alternatively as a uisplitviewcontroller inspector pane. When pushed (initially compact size class, then opened to regular), toolbar items are moved to the side as expected: however when presented in an inspector pane the toolbar items are not moved to the side: The toolbaritems contain one less image in the later case. iOS 27.1 simulator
Topic: UI Frameworks SubTopic: UIKit
1
0
209
8h
Keeping compatibility mode
Hi, is there any possibility of developers being able to keep compatibility mode for a particular device model? I know it is possible for the iPad because it is regarded as a different device family from the iPhone. We wonder if it is possible for us to target just a particular model. Say for example, the iPhone Duo.
Topic: UI Frameworks SubTopic: General
0
0
210
12h
AsyncRenderer causes crashes in ForEach when in Swift 6 language mode
Hi! We've recently done a big migration to Swift 6 language mode in our app and are now getting reports of crashes occurring due to closures in our SwiftUI code (most often the view builder in ForEach) not running on the main queue but instead running on the queue com.apple.SwiftUI.AsyncRenderer. One example of a call stack (ScheduleListView is our view that is in Swift 6 mode): Thread 16 #0 (null) in _dispatch_assert_queue_fail () #1 (null) in dispatch_assert_queue$V2.cold.1 () #2 (null) in dispatch_assert_queue () #3 (null) in swift_task_isCurrentExecutorWithFlagsImpl(swift::SerialExecutorRef, swift::swift_task_is_current_executor_flag) () #4 (null) in closure #2 in closure #1 in closure #1 in ScheduleListView.body.getter () #5 (null) in closure #1 in ForEachState.item(at:offset:) () #6 (null) in partial apply for closure #1 in ForEachState.item(at:offset:) () #8 (null) in partial apply for closure #1 in _withObservation<A>(do:) () .... (We have many other crashes with similar crash reports but in other views) Has anybody else run into something similar? Is there anything (other than simply reverting to Swift 5 mode again) that we can do to fix or at least reduce the amount of crashes? We're having a hard time finding anything out of the ordinary that we're doing in our views. Regards
Topic: UI Frameworks SubTopic: SwiftUI
7
6
1.1k
14h
Table focus bug in macOS 27
When I click on a table row, the focus cannot be changed from a TextField to the table. This is a bug in macOS 27 because the focus can be changed from a TextField to the table in macOS 26. Temp workaround: Click a different window, such as Finder or Safari Click the table in my app. The focus can be changed from a different app to the table in my app. Note: Table with focus: the table row is highlighted in blue. Table without focus: the table row is highlighted in grey.
Topic: UI Frameworks SubTopic: SwiftUI
2
1
547
15h
SwiftUI `OutlineGroup` Should Support Native Reordering with `reorderable` / `reorderContainer`
Description I would like to request native reordering support for SwiftUI hierarchical views, especially OutlineGroup and List(_:children:). In iOS 27, SwiftUI introduces the new reordering APIs: .reorderable() .reorderable(collectionID:) .reorderContainer(for:move:) .reorderContainer(for:in:move:) These APIs work well for flat collections and explicit sectioned collections, but they do not appear to integrate with OutlineGroup, even though OutlineGroup is the natural SwiftUI API for tree-structured data. Currently, OutlineGroup hides the internal recursive ForEach / DisclosureGroup structure, so there is no obvious place to apply reorderable(collectionID:) at each hierarchy level. Current Working Pattern for Sections This works when each parent is represented manually as a section: struct SectionModel: Identifiable { let id: UUID var title: String var items: [Item] } struct Item: Identifiable { let id: UUID var title: String } struct ContentView: View { @State private var sections: [SectionModel] = sampleSections var body: some View { List { ForEach(sections) { section in Section(section.title) { ForEach(section.items) { item in Text(item.title) } .reorderable(collectionID: section.id) } } } .reorderContainer(for: Item.self, in: SectionModel.ID.self) { difference in apply(difference) } } private func apply(_ difference: ReorderDifference<Item.ID, SectionModel.ID>) { // Move item between explicit sections. } } But this does not scale naturally to arbitrary tree data. Desired API Ideally, this should work with OutlineGroup: struct Node: Identifiable { let id: UUID var title: String var children: [Node]? } struct ContentView: View { @State private var nodes: [Node] = sampleTree var body: some View { List { OutlineGroup(nodes, children: \.children) { node in Text(node.title) } .reorderable() } .reorderContainer(for: Node.self) { difference in apply(difference) } } private func apply(_ difference: ReorderDifference<Node.ID, ???>) { // Move node within the tree. } } For hierarchical data, SwiftUI would need to expose the parent or collection identity of the source and destination. For example, something like: .reorderableTree( children: \.children, allowsMoveIntoChildren: true ) Or an overload such as: OutlineGroup(nodes, children: \.children) { node in Text(node.title) } .reorderable(collectionID: \.parentID) With a ReorderDifference that includes: sourceParentID destinationParentID destinationPosition movedItemIDs Why This Matters Many apps represent user-created hierarchical data: folders bookmark collections nested lists project outlines document trees sidebar hierarchies OutlineGroup is the natural SwiftUI abstraction for displaying this data, but reordering currently requires either: 1abandoning OutlineGroup and rebuilding a recursive outline manually; 2flattening the hierarchy into sections, losing the real outline interaction; 3using older manual drag/drop APIs; 4falling back to UIKit/AppKit. None of these approaches feels aligned with SwiftUI's declarative model. Specific Request Please consider adding native reorder support to OutlineGroup and List(_:children:), including support for: moving items within the same parent; moving items between parents; optionally moving an item into another item as a child; preventing invalid moves, such as moving a parent into one of its descendants; exposing source and destination parent identifiers in the move callback; preserving SwiftUI's built-in disclosure UI. Minimal Example of the Current Limitation This is the kind of code I would expect to be possible: List { OutlineGroup(nodes, children: \.children) { node in Text(node.title) } .reorderable() } .reorderContainer(for: Node.self, in: Node.ID.self) { difference in moveNode(using: difference) } But because OutlineGroup creates its recursive rows internally, there is no clear way to attach reorderable(collectionID:) to each parent's child collection. Expected Outcome SwiftUI should provide a first-class way to reorder hierarchical data displayed with OutlineGroup, similar to how flat and sectioned collections can now use reorderable and reorderContainer.
Topic: UI Frameworks SubTopic: SwiftUI
2
2
143
16h
Keyboard extensions and reserved regions
I have a keyboard extension in my app and I'm seeing some inconsistent behavior with the system-provided Globe and Dictation buttons. For the system keyboards, these buttons are displayed to the side of the keyboard, insetting the bottom row of keys on the folded screen and insetting the entire keyboard on the unfolded screen. What is the expected behavior for custom keyboards on the folded screen? My test results: When the Duo simulator is folded, sometimes the Globe and Dictation buttons appear next to my keyboard and the entire custom keyboard is squeezed to be really narrow. Other times my UI gets the full width and the Globe and Dictate keys are on TOP of my UI. The latter seems preferable, assuming I can then use the reserved regions API to avoid the overlap. Is that the intent? PS: The reserved regions API doesn't seem to work in keyboard extensions in this beta, neither in SwiftUI or UIKit. Hopefully that's fixed in the next beta.
Topic: UI Frameworks SubTopic: UIKit
1
1
63
17h
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
6
9
729
17h
Where do scroll indicators go on iPhone Duo?
In the process of updating an app for the iPhone Duo, I initially changed scroll/collection view leading/trailing to use the safe area. This puts the scroll indicators "inside" the side navigation bar: But looking at both Safari and Settings, the scroll indicators are placed "outside" the navigation bar: This leads to a couple of questions: Is the "outside" placement correct for a view with scrolling content? Is there a way to achieve this without reorganizing the scroll view content? The only solution I've found is to place a new container view inside a scroll view that uses the superview as its edge constraints. The container view gets placed using safe areas. If there's an easier way, I'd love to know what it is.
Topic: UI Frameworks SubTopic: UIKit
1
1
551
19h
Back button briefly jumps to the leading edge of the navigation bar during interactive pop from a screen with a hidden navigation bar (iPhone Duo)
On the iPhone Duo's narrow display, the navigation bar's back button sits in the trailing column below the status bar. During an interactive swipe-back from a screen whose navigation bar is hidden to a screen whose navigation bar is visible, the back button briefly renders in the leading (top-left) position of the bar for one or more frames. In those same frames the trailing-column button is blank. It then jumps back to the trailing column. The result is a visible flicker. Steps to reproduce: Open the attached code in Xcode 27.1 and run it on the iPhone Duo simulator (iOS 27.1), using the narrow display in portrait. Tap "Push". This pushes a screen with a visible navigation bar. Tap "Push without header". This pushes a screen that hides the navigation bar. Slowly swipe back from the leading edge to return to the previous screen. Expected: the back button of the revealed navigation bar stays in the trailing column for the whole transition, the same as with a programmatic pop. Actual: for one or more frames during the gesture, the back button renders at the leading edge of the navigation bar (top-left), and the trailing column is blank. Then it returns to the trailing column. Repro: import UIKit @main final class AppDelegate: UIResponder, UIApplicationDelegate {} final class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options: UIScene.ConnectionOptions) { guard let windowScene = scene as? UIWindowScene else { return } let window = UIWindow(windowScene: windowScene) let nav = SwipeableNavigationController(rootViewController: ScreenVC(title: "header 0", showsHeader: true)) window.rootViewController = nav window.makeKeyAndVisible() self.window = window // Auto sequence when launched with `-auto YES`: push header, push no header, pop. guard UserDefaults.standard.bool(forKey: "auto") else { return } DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { nav.pushViewController(ScreenVC(title: "header 0", showsHeader: true), animated: true) } DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) { nav.pushViewController(ScreenVC(title: "no header", showsHeader: false), animated: true) } DispatchQueue.main.asyncAfter(deadline: .now() + 4.5) { nav.popViewController(animated: true) } } } final class ScreenVC: UIViewController { private let showsHeader: Bool init(title: String, showsHeader: Bool) { self.showsHeader = showsHeader super.init(nibName: nil, bundle: nil) self.title = title } required init?(coder: NSCoder) { fatalError() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) navigationController?.setNavigationBarHidden(!showsHeader, animated: animated) } override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .systemGroupedBackground let push = UIButton(configuration: .plain(), primaryAction: UIAction(title: "Push") { [weak self] _ in self?.navigationController?.pushViewController(ScreenVC(title: "header 0", showsHeader: true), animated: true) }) let pushNoHeader = UIButton(configuration: .plain(), primaryAction: UIAction(title: "Push without header") { [weak self] _ in self?.navigationController?.pushViewController(ScreenVC(title: "no header", showsHeader: false), animated: true) }) let back = UIButton(configuration: .plain(), primaryAction: UIAction(title: "Go back") { [weak self] _ in self?.navigationController?.popViewController(animated: true) }) let stack = UIStackView(arrangedSubviews: [push, pushNoHeader, back]) stack.axis = .vertical stack.translatesAutoresizingMaskIntoConstraints = false view.addSubview(stack) NSLayoutConstraint.activate([ stack.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 10), stack.centerXAnchor.constraint(equalTo: view.centerXAnchor), ]) } } final class SwipeableNavigationController: UINavigationController, UIGestureRecognizerDelegate { override func viewDidLoad() { super.viewDidLoad() interactivePopGestureRecognizer?.delegate = self if #available(iOS 26.0, *) { interactiveContentPopGestureRecognizer?.delegate = self } } func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { viewControllers.count > 1 } } Thank you in advance!
1
1
203
23h
UISwitch's Liquid Glass toggle glow/shadow (iOS 26) is not clipped by a UIModalPresentationFormSheet / clipsToBounds container
Summary: On iOS 26, UISwitch has a Liquid Glass dynamic highlight/shadow effect that is not clipped by an ancestor view's bounds, even inside a UIModalPresentationFormSheet card. This is visible in two ways: (1) a plain tap on a switch positioned near the form sheet's edge already shows the highlight/shadow rendering outside the card's rounded border; (2) pressing and dragging the finger away from the switch drags this effect along with the touch, and it can end up rendered far outside the form sheet, well past the presentation area. Steps to Reproduce: Run the attached minimal project on an iOS 26 device/simulator. Tap "Present Form Sheet" to present a UIModalPresentationFormSheet containing a UITableView, with a UISwitch near the trailing edge of each row. Simply tap a switch near the sheet's edge — notice the dynamic highlight/shadow already overflows past the form sheet's rounded border. Now press and hold a switch, then quickly swipe/drag the finger downward (or in any direction) without lifting — notice the highlight/shadow follows the finger and gets dragged far outside the form sheet's bounds, over the dimmed presentation background. Expected Results: The Liquid Glass dynamic highlight/shadow effect should be clipped to the bounds of the form sheet card at all times, whether triggered by a plain tap or a drag gesture. Actual Results: On a plain tap near the edge: the highlight/shadow already overflows just past the form sheet's rounded border, unclipped. On press-and-drag: the highlight/shadow follows the finger and can be dragged far outside the form sheet — well beyond the card's edges and the presentation area. Configuration: iOS 26.x simulator/device Xcode 26.x // LiquidGlassSwitchDemo // // Minimal repro: UISwitch's Liquid Glass transition effect (iOS 26) is not // clipped by a UIModalPresentationFormSheet card, which clips everything else. // #import "AppDelegate.h" // Form sheet content: a table view full of UISwitch cells. @interface WMSwitchGlassCardViewController : UIViewController <UITableViewDataSource> @end @implementation WMSwitchGlassCardViewController - (void)viewDidLoad { [super viewDidLoad]; self.preferredContentSize = CGSizeMake(320, 400); UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleInsetGrouped]; tableView.dataSource = self; tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self.view addSubview:tableView]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 8; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]; cell.textLabel.text = [NSString stringWithFormat:@"Option %ld", (long)indexPath.row + 1]; UISwitch *toggle = [[UISwitch alloc] init]; toggle.on = YES; cell.accessoryView = toggle; // Actual: while toggling, the glass glow/shadow renders outside the form // sheet's rounded corners and floats over the dimmed background — the // card's clipsToBounds / rounded corners have no effect on the effect. return cell; } @end // Root screen: a single button that presents the card above as a form sheet. @interface WMRootViewController : UIViewController @end @implementation WMRootViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = UIColor.systemBackgroundColor; UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; [button setTitle:@"Present Form Sheet" forState:UIControlStateNormal]; [button addTarget:self action:@selector(presentCard) forControlEvents:UIControlEventTouchUpInside]; button.translatesAutoresizingMaskIntoConstraints = NO; [self.view addSubview:button]; [NSLayoutConstraint activateConstraints:@[ [button.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor], [button.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor], ]]; } - (void)presentCard { UIViewController *card = [WMSwitchGlassCardViewController new]; card.modalPresentationStyle = UIModalPresentationFormSheet; [self presentViewController:card animated:YES completion:nil]; } @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds]; self.window.rootViewController = [WMRootViewController new]; [self.window makeKeyAndVisible]; return YES; } @end```
Topic: UI Frameworks SubTopic: UIKit Tags:
0
0
190
1d
UISwitch's Liquid Glass toggle glow/shadow (iOS 26) is not clipped by a UIModalPresentationFormSheet / clipsToBounds container
Summary: On iOS 26, UISwitch has a Liquid Glass dynamic highlight/shadow effect that is not clipped by an ancestor view's bounds, even inside a UIModalPresentationFormSheet card. This is visible in two ways: (1) a plain tap on a switch positioned near the form sheet's edge already shows the highlight/shadow rendering outside the card's rounded border; (2) pressing and dragging the finger away from the switch drags this effect along with the touch, and it can end up rendered far outside the form sheet, well past the presentation area. Steps to Reproduce: Run the attached minimal project on an iOS 26 device/simulator. Tap "Present Form Sheet" to present a UIModalPresentationFormSheet containing a UITableView, with a UISwitch near the trailing edge of each row. Simply tap a switch near the sheet's edge — notice the dynamic highlight/shadow already overflows past the form sheet's rounded border. Now press and hold a switch, then quickly swipe/drag the finger downward (or in any direction) without lifting — notice the highlight/shadow follows the finger and gets dragged far outside the form sheet's bounds, over the dimmed presentation background. Expected Results: The Liquid Glass dynamic highlight/shadow effect should be clipped to the bounds of the form sheet card at all times, whether triggered by a plain tap or a drag gesture. Actual Results: On a plain tap near the edge: the highlight/shadow already overflows just past the form sheet's rounded border, unclipped. On press-and-drag: the highlight/shadow follows the finger and can be dragged far outside the form sheet — well beyond the card's edges and the presentation area. Configuration: iOS 26.x simulator/device Xcode 26.x // AppDelegate.m // LiquidGlassSwitchDemo // // Minimal repro: UISwitch's Liquid Glass transition effect (iOS 26) is not // clipped by a UIModalPresentationFormSheet card, which clips everything else. // #import "AppDelegate.h" // Form sheet content: a table view full of UISwitch cells. @interface WMSwitchGlassCardViewController : UIViewController <UITableViewDataSource> @end @implementation WMSwitchGlassCardViewController - (void)viewDidLoad { [super viewDidLoad]; self.preferredContentSize = CGSizeMake(320, 400); UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleInsetGrouped]; tableView.dataSource = self; tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self.view addSubview:tableView]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 8; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]; cell.textLabel.text = [NSString stringWithFormat:@"Option %ld", (long)indexPath.row + 1]; UISwitch *toggle = [[UISwitch alloc] init]; toggle.on = YES; cell.accessoryView = toggle; // Actual: while toggling, the glass glow/shadow renders outside the form // sheet's rounded corners and floats over the dimmed background — the // card's clipsToBounds / rounded corners have no effect on the effect. return cell; } @end // Root screen: a single button that presents the card above as a form sheet. @interface WMRootViewController : UIViewController @end @implementation WMRootViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = UIColor.systemBackgroundColor; UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; [button setTitle:@"Present Form Sheet" forState:UIControlStateNormal]; [button addTarget:self action:@selector(presentCard) forControlEvents:UIControlEventTouchUpInside]; button.translatesAutoresizingMaskIntoConstraints = NO; [self.view addSubview:button]; [NSLayoutConstraint activateConstraints:@[ [button.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor], [button.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor], ]]; } - (void)presentCard { UIViewController *card = [WMSwitchGlassCardViewController new]; card.modalPresentationStyle = UIModalPresentationFormSheet; [self presentViewController:card animated:YES completion:nil]; } @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds]; self.window.rootViewController = [WMRootViewController new]; [self.window makeKeyAndVisible]; return YES; } @end``` ![]("https://developer.apple.com/forums/content/attachment/3f8e87c4-d99f-4c03-adf8-b2c12a54aa8d" "title=20260928-151703@2x.png;width=666;height=644") ![]("https://developer.apple.com/forums/content/attachment/602ca9f8-c604-4168-9242-17d74c93b644" "title=20260928-151745@2x.png;width=544;height=396")
1
0
33
1d
There is a bug regarding CoreText.
When the end of the line is a Chinese symbol, it may appear that the rendering is based on the width of the visible content of the symbol, without considering the side bearing of the Chinese symbol, while the layout is calculated based on the full width of the Chinese symbol. The Chinese symbols should have been placed on the next line for rendering, but they ended up being partially placed on the previous line, resulting in a blank line below. Please refer to the Chinese exclamation mark in the attached image for details
Topic: UI Frameworks SubTopic: General
0
0
28
1d
Hinge listeners don't work in Keyboard Extension on iPhone Duo (iOS 27.1)
Hi, I've discovered that my Keyboard Extension is unable to detect any hinge status update on iPhone Duo. I tired both UIKit and SwiftUI approach - nothing works. Is there any workaround to make it work? Reproducible demo: https://www.icloud.com/iclouddrive/0460exMJtAdRkpk8EDjb751nw Xcode 27.1 (27A9269) iOS 27.1 beta 1 (24A94401) I also created a bug report: FB24883137
2
1
332
1d
iOS 27: UIApplication.shared.open fail for relative URL values that resolve to valid https URLs
A URL created with URL(string:relativeTo:) that used to work in iOS26 and below with UIApplication.shared.open stopped working in iOS27, the app has not been built yet with iOS27 SDK. Have anyone seen this issue, all the links work perfectly in iOS26 and below. We found a solution to use .absoluteURL but still want to check with the community, I havent seen any mention of this this that it will break try the below sample code import UIKit struct RelativeURLReproView: View { @State private var log = "Tap a button. Watch this log and whether Safari actually appears.\n" var body: some View { VStack(alignment: .leading, spacing: 16) { Button("Open relative URL") { openTarget(.relative) } .buttonStyle(.borderedProminent) Button("Open absoluteURL") { openTarget(.absolute) } .buttonStyle(.bordered) Button("Clear log") { log = "" } ScrollView { Text(log) .font(.system(.footnote, design: .monospaced)) .textSelection(.enabled) .frame(maxWidth: .infinity, alignment: .leading) } } .padding() } private enum ReproTarget { case relative case absolute } private func append(_ line: String) { log.append(line + "\n") print(line) } private func openTarget(_ target: ReproTarget) { log = "" let base = URL(string: "https://www.example.com")! let relative = URL(string: "about/help", relativeTo: base)! let url = (target == .relative) ? relative : relative.absoluteURL append("target: \(target == .relative ? "relative" : "absoluteURL")") append("url: \(url)") append("absoluteString: \(url.absoluteString)") append("scheme: \(url.scheme ?? "nil")") append("baseURL: \(url.baseURL?.absoluteString ?? "nil")") append("relativeString: \(url.relativeString)") append("canOpenURL: \(UIApplication.shared.canOpenURL(url))") append("Calling UIApplication.shared.open…") append("Did Safari actually appear? Check by eye.") UIApplication.shared.open(url, options: [:]) { success in Task { @MainActor in append("open completion: \(success)") } } } } #Preview { RelativeURLReproView() }
5
0
163
1d
Simple solution for visibilityPriority for toolbar items.
The iPhone Duo provides varying space for toolbar items based on screen orientation. One approach uses .visibilityPriority(_) to keep higher-priority items visible longer as the window shrinks and items go to the overflow menu. For instance: .toolbar { ToolbarItem { SecondaryControl() } ToolbarItem { PrimaryControl() } .visibilityPriority(.high) } The problem is that .visibilityPriority(_) requires iOS 27 or later, while typical apps aim for older systems such as iOS 26. What is your solution to keep the code simple?
Topic: UI Frameworks SubTopic: SwiftUI Tags:
4
0
86
1d
TimePicker numeric pad popover renders as a narrow bar on iPadOS 26.4.1
When tapping the currently selected time in a TimePicker (wheel style) component to invoke the inline numeric pad popover, the popover renders incorrectly on iPadOS 26.4.1 — it appears as a very narrow single-line/bar rather than the full numeric keypad layout. Steps to Reproduce: Run Reminder, create a new reminder and add a custom time Tap the currently selected time value to trigger the numeric pad popover Observe the popover layout Expected Result: A properly sized popover appears containing a full numeric keypad, allowing direct numeric input of the time value — consistent with behavior on iPadOS 18.x Actual Result: The popover appears as an extremely narrow horizontal bar (single line height), making the numeric pad unusable Regression: Works correctly on iPadOS 18.x through iPadOS 26.3. Broken on iPadOS 26.4.1 (Xcode 26.x simulator and/or physical device). https://www.youtube.com/shorts/bd3pYA3B-iI https://www.youtube.com/shorts/wSHzepHBwEY Feedback: FB22517457
Topic: UI Frameworks SubTopic: UIKit
6
2
1.1k
1d
A Summary of the iPhone Duo Group Lab
Group Labs are a unique opportunity for the community to submit questions directly to a panel of Apple engineers and designers. Here are the highlights from the iPhone Duo Group Labs: How should apps preserve navigation and UI state when switching between the inner and outer displays? Treat display transitions as size-class and trait changes, not a scene disconnect or app termination; your process stays alive. For more information, see Prepare your app for iPhone Duo. For state that must survive a scene disconnect/reconnect, implement stateRestorationActivity(for:) to save an NSUserActivity Restoring your app's state. Do multiple instances of the same app on iPhone Duo share UserDefaults/@AppStorage state? Multiple instances of your app's UI on iPhone Duo behave similarly to multi-window support on iPadOS. To learn more, see Leverage multiple displays and scenes on iPhone Duo. Both UserDefaults and AppStorage are app-wide, not per-window, stores. If a full-screen app on the inner display is closed, does it move to the outer display or get backgrounded? iPhone Duo honors UIRequiresFullScreen and apps adapt in place as the device opens and closes rather than backgrounding. To learn more, watch Prepare your app for iPhone Duo. How should apps preserve state — text input, scroll position, video playback, camera sessions — during hinge angle transitions? For example, when a LazyVGrid's column count changes because the device folds, does SwiftUI preserve scroll position automatically, or should you use scrollPosition(id:)? The system generally preserves text input and scroll position automatically since hinge angle changes are represented as size-class and trait updates, not a scene disconnect or app termination. This applies even to cases like a LazyVGrid column-count change triggered by opening or closing the device — apps typically don't need to manually manage scroll position with scrollPosition(id:anchor:) for this transition. For more info, see Prepare your app for iPhone Duo. How can apps preserve what someone is doing when switching displays or folding/unfolding? Treat this as a resize/trait-change event, not app teardown — your process keeps running as size classes change. See Prepare your app for iPhone Duo to learn more. For scenes that actually disconnect and reconnect, implement stateRestorationActivity(for:) to save an NSUserActivity Restoring your app's state. How does actively playing video behave through the hinge angle animation? The system generally preserves video playback and player position automatically since hinge angle changes are represented as size-class and trait updates, not a scene disconnect or app termination. AVKit will scale and resize the video automatically. If a user folds or unfolds the device mid-checkout, what does the system preserve automatically, and what should the app manage itself to avoid lost input or duplicate requests? When someone opens or closes an iPhone Duo, the system represents this as a size-class and trait collection change, not a scene disconnect or app teardown, so in-memory state like input fields typically persists automatically since the app’s process keeps running. For more info, see Prepare your app for iPhone Duo. How should apps handle the keyboard and text input when the device folds or unfolds while typing? As iPhone Duo folds or unfolds, the available screen geometry and framing change. Ensure your app adopts standard layout controls, containers, and size classes to handle resizability gracefully across all poses. When a text field becomes first responder, the system automatically shows the keyboard and binds its input to the text field. Because the appearance of the keyboard has the potential to obscure portions of your user interface, you should update your interface as needed to ensure that the text field being edited remains visible. Use keyboard notifications such as keyboardWillShowNotification, keyboardWillHideNotification, and keyboardWillChangeFrameNotification to detect the appearance and disappearance of the keyboard and to make necessary changes to your interface layout. To learn more, see UITextField. If someone is typing and closes iPhone Duo, does the keyboard/editing session survive the hinge transition, or does it get a new scene? When a user types and closes iPhone Duo, the active editing session and keyboard do not get a completely new scene. Instead, the app undergoes a dynamic resizing and transitions from the inner display to the compact outer display, maintaining the existing scene and application state. For more info, watch Prepare your app for iPhone Duo.
Replies
16
Boosts
0
Views
1.5k
Activity
5d
Show onboarding steps side by side on iPhone Duo
Hi, I'm currently in the process of updating my app, which only supports iPhone at the moment, and I'm wondering how I could update my onboarding flow to take advantage of the iPhone Duo when unfolded. Basically the onboarding is a succession of screens, all presented inside a NavigationStack one after the other. I had the idea of using all the screen area to show those screens 2 by 2 (side by side). At first I thought about using NavigationSplitView to accomplish this (pairs of them) but I couldn't get a 50/50 ratio and it felt more of a hack. I then turned my attention to ArrangementView using an horizontal split but in certain layouts only the primary is shown and I'm not sure how I can detect that to show the secondary on push. Would anybody know what the best way would be to accomplish this? Or is it not a good idea at all? Thanks!
Topic: UI Frameworks SubTopic: SwiftUI
Replies
0
Boosts
0
Views
15
Activity
1h
iPadOS 27.0.1: iPhone-only apps crash when displaying the Japanese Kana keyboard on iPad
We are seeing a crash when attempting to display the Japanese Kana keyboard (日本語-かな) in our iPhone-only app running on an iPad with iPadOS 27.0.1. The keyboard displays successfully in our app on iPadOS 26 and iPadOS 27.0. We also reproduced a similar crash in other iPhone-only apps downloaded from the App Store on the affected iPad. We have not yet confirmed whether those apps crash with the same exception. Our app logs the following exception: *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM insertObject:atIndex:]: index 15 beyond bounds [0 .. 2]' *** First throw call stack: ( 0x19fab7190 0x19f834380 0x19fa45734 0x1aee9f5bc 0x1aee3dc14 0x1aee3cb30 0x1aee3c4d4 0x1aee3ab0c 0x1a433798c 0x1a44a4120 0x1a449bd5c 0x1a42148c8 0x1a42143fc 0x1a4239d7c 0x1a421203c 0x1a3fc1338 0x1a3d12e0c 0x1a3d11ed0 0x1a52784ec 0x1a3d11abc 0x1a4115238 0x1a3d436d4 0x1a3d43a80 0x1a44eea14 0x1aabb8ef8 0x1a517161c 0x1a5152450 0x1a5153388 0x1a41f20c4 0x1a49e3fec 0x1a426598c 0x1a42657fc 0x1a4265580 0x1a3d62b30 0x1a3d62984 0x1a95c4dac 0x1a994fb68 0x1a95c5514 0x1a95c287c 0x1a95d2608 0x1a3d6841c 0x1a3d6a298 0x1a4263874 0x1a3d60bdc 0x1a3ce8d78 0x1a3ce7b88 0x1a3ce7928 0x2d1482bc0 0x19fa78c20 0x19fa78b94 0x19fa5a268 0x19fa59384 0x19fa5a7f4 0x249e6ff24 0x1a3d381cc 0x1a9d27404 0x1a9d20b50 0x1a9d20a10 0x109042dc4 0x109042e04 0x19f8ab5b8 ) libc++abi: terminating due to uncaught exception of type NSException Steps to reproduce: Enable the Japanese – Kana keyboard in the iPad’s keyboard settings. Open an affected iPhone-only app on an iPad running iPadOS 27.0.1. Tap a text input field and attempt to display the Japanese Kana keyboard. The app crashes. We suspect this may be a regression involving iPhone compatibility mode on iPad and the Japanese Kana keyboard, but we have not yet identified the failing component in a symbolicated stack trace. We have submitted a report through Feedback Assistant: FB24985530. Has anyone else encountered this behavior? Are there any known workarounds we can apply in the app while this is being investigated?
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
0
Boosts
0
Views
24
Activity
1h
Sandboxed macOS dictation: insert at the current focused input across apps
Update: I clarified the intended behavior after posting. The destination is the text input that has keyboard focus when the finished dictation is delivered, even if the user changed fields or apps while speaking. We do not need to return to the field where dictation started. I’m building a macOS dictation app for the Mac App Store, so it must run with App Sandbox enabled. For example, a user might start dictating with an input in Chrome focused, then click into a ChatGPT input while speaking. When the result is ready, it should insert at the ChatGPT caret. Moving the caret within one app should likewise change the destination. In an isolated signed sandboxed prototype, I write a marker to the general pasteboard and post Command–V with CGEvent.post after the user grants event-posting access. This inserts successfully in TextEdit at the current caret, including after a same-document caret move. That result is now consistent with the intended behavior. The prototype also has a frontmost-process guard that withholds insertion after an app switch; that is our own guard and could be removed. We have not yet verified cross-app delivery without it. The existing nonsandboxed app uses AXUIElement to inspect the focused field. Apple’s App Sandbox documentation lists assistive Accessibility APIs as incompatible with sandboxed apps. For a current-focus insertion design, is there any supported sandbox-compatible way to know whether the destination has a focused editable field or is a secure input, or to learn whether a posted paste was actually accepted? If not, is relying on the destination app’s paste handling and retaining the transcript for manual recovery the expected approach? I also tested an AppKit Service. TextEdit inserts its returned text when the caret stays put; after a physical click to another caret during a pending request, the provider returns but TextEdit inserts nothing. This does not appear to fit our hold-to-dictate, switch-apps-while-speaking interaction. I’d welcome experience with another system-mediated approach that does. Environment: macOS 27.0, Xcode 27.0, Apple Silicon. I’m asking about technical API behavior and implementation patterns, not a guarantee of App Review approval.
Replies
1
Boosts
0
Views
236
Activity
5h
Unexpected sceneDidBecomeActive called during screen lock in iOS 27
I've noticed a strange issue with the SceneDelegate lifecycle in iOS 27. [Environment] iOS 27 (Also tested on physical devices) UIKit / SceneDelegate based App [Description & Steps to Reproduce] When the app is in the foreground and the user locks the screen (presses the power button): In iOS 26 and earlier: sceneWillResignActive is called exactly once. (Expected behavior) In iOS 27: The following sequence is called rapidly in succession: sceneWillResignActive (Screen lock initiated) sceneDidBecomeActive sceneWillResignActive (Locks completely) When the user unlocks the screen later, sceneDidBecomeActive is called once as usual. [Impact] Because sceneDidBecomeActive is unexpectedly fired while the device is locking, it triggers foreground logics right before the app is pushed to the background. This is causing unwanted side-effects and glitches. Has anyone else encountered this unbalanced lifecycle issue in iOS 27? I'd like to know if there's a better approach or if Apple is aware of this. Thanks!
Replies
1
Boosts
1
Views
51
Activity
7h
iPhone duo toolbar items misplaced for inspector view
I am displaying the same view via a push onto the secondary view of a modern uisplitviewcontroller and alternatively as a uisplitviewcontroller inspector pane. When pushed (initially compact size class, then opened to regular), toolbar items are moved to the side as expected: however when presented in an inspector pane the toolbar items are not moved to the side: The toolbaritems contain one less image in the later case. iOS 27.1 simulator
Topic: UI Frameworks SubTopic: UIKit
Replies
1
Boosts
0
Views
209
Activity
8h
Keeping compatibility mode
Hi, is there any possibility of developers being able to keep compatibility mode for a particular device model? I know it is possible for the iPad because it is regarded as a different device family from the iPhone. We wonder if it is possible for us to target just a particular model. Say for example, the iPhone Duo.
Topic: UI Frameworks SubTopic: General
Replies
0
Boosts
0
Views
210
Activity
12h
AsyncRenderer causes crashes in ForEach when in Swift 6 language mode
Hi! We've recently done a big migration to Swift 6 language mode in our app and are now getting reports of crashes occurring due to closures in our SwiftUI code (most often the view builder in ForEach) not running on the main queue but instead running on the queue com.apple.SwiftUI.AsyncRenderer. One example of a call stack (ScheduleListView is our view that is in Swift 6 mode): Thread 16 #0 (null) in _dispatch_assert_queue_fail () #1 (null) in dispatch_assert_queue$V2.cold.1 () #2 (null) in dispatch_assert_queue () #3 (null) in swift_task_isCurrentExecutorWithFlagsImpl(swift::SerialExecutorRef, swift::swift_task_is_current_executor_flag) () #4 (null) in closure #2 in closure #1 in closure #1 in ScheduleListView.body.getter () #5 (null) in closure #1 in ForEachState.item(at:offset:) () #6 (null) in partial apply for closure #1 in ForEachState.item(at:offset:) () #8 (null) in partial apply for closure #1 in _withObservation<A>(do:) () .... (We have many other crashes with similar crash reports but in other views) Has anybody else run into something similar? Is there anything (other than simply reverting to Swift 5 mode again) that we can do to fix or at least reduce the amount of crashes? We're having a hard time finding anything out of the ordinary that we're doing in our views. Regards
Topic: UI Frameworks SubTopic: SwiftUI
Replies
7
Boosts
6
Views
1.1k
Activity
14h
Table focus bug in macOS 27
When I click on a table row, the focus cannot be changed from a TextField to the table. This is a bug in macOS 27 because the focus can be changed from a TextField to the table in macOS 26. Temp workaround: Click a different window, such as Finder or Safari Click the table in my app. The focus can be changed from a different app to the table in my app. Note: Table with focus: the table row is highlighted in blue. Table without focus: the table row is highlighted in grey.
Topic: UI Frameworks SubTopic: SwiftUI
Replies
2
Boosts
1
Views
547
Activity
15h
SwiftUI `OutlineGroup` Should Support Native Reordering with `reorderable` / `reorderContainer`
Description I would like to request native reordering support for SwiftUI hierarchical views, especially OutlineGroup and List(_:children:). In iOS 27, SwiftUI introduces the new reordering APIs: .reorderable() .reorderable(collectionID:) .reorderContainer(for:move:) .reorderContainer(for:in:move:) These APIs work well for flat collections and explicit sectioned collections, but they do not appear to integrate with OutlineGroup, even though OutlineGroup is the natural SwiftUI API for tree-structured data. Currently, OutlineGroup hides the internal recursive ForEach / DisclosureGroup structure, so there is no obvious place to apply reorderable(collectionID:) at each hierarchy level. Current Working Pattern for Sections This works when each parent is represented manually as a section: struct SectionModel: Identifiable { let id: UUID var title: String var items: [Item] } struct Item: Identifiable { let id: UUID var title: String } struct ContentView: View { @State private var sections: [SectionModel] = sampleSections var body: some View { List { ForEach(sections) { section in Section(section.title) { ForEach(section.items) { item in Text(item.title) } .reorderable(collectionID: section.id) } } } .reorderContainer(for: Item.self, in: SectionModel.ID.self) { difference in apply(difference) } } private func apply(_ difference: ReorderDifference<Item.ID, SectionModel.ID>) { // Move item between explicit sections. } } But this does not scale naturally to arbitrary tree data. Desired API Ideally, this should work with OutlineGroup: struct Node: Identifiable { let id: UUID var title: String var children: [Node]? } struct ContentView: View { @State private var nodes: [Node] = sampleTree var body: some View { List { OutlineGroup(nodes, children: \.children) { node in Text(node.title) } .reorderable() } .reorderContainer(for: Node.self) { difference in apply(difference) } } private func apply(_ difference: ReorderDifference<Node.ID, ???>) { // Move node within the tree. } } For hierarchical data, SwiftUI would need to expose the parent or collection identity of the source and destination. For example, something like: .reorderableTree( children: \.children, allowsMoveIntoChildren: true ) Or an overload such as: OutlineGroup(nodes, children: \.children) { node in Text(node.title) } .reorderable(collectionID: \.parentID) With a ReorderDifference that includes: sourceParentID destinationParentID destinationPosition movedItemIDs Why This Matters Many apps represent user-created hierarchical data: folders bookmark collections nested lists project outlines document trees sidebar hierarchies OutlineGroup is the natural SwiftUI abstraction for displaying this data, but reordering currently requires either: 1abandoning OutlineGroup and rebuilding a recursive outline manually; 2flattening the hierarchy into sections, losing the real outline interaction; 3using older manual drag/drop APIs; 4falling back to UIKit/AppKit. None of these approaches feels aligned with SwiftUI's declarative model. Specific Request Please consider adding native reorder support to OutlineGroup and List(_:children:), including support for: moving items within the same parent; moving items between parents; optionally moving an item into another item as a child; preventing invalid moves, such as moving a parent into one of its descendants; exposing source and destination parent identifiers in the move callback; preserving SwiftUI's built-in disclosure UI. Minimal Example of the Current Limitation This is the kind of code I would expect to be possible: List { OutlineGroup(nodes, children: \.children) { node in Text(node.title) } .reorderable() } .reorderContainer(for: Node.self, in: Node.ID.self) { difference in moveNode(using: difference) } But because OutlineGroup creates its recursive rows internally, there is no clear way to attach reorderable(collectionID:) to each parent's child collection. Expected Outcome SwiftUI should provide a first-class way to reorder hierarchical data displayed with OutlineGroup, similar to how flat and sectioned collections can now use reorderable and reorderContainer.
Topic: UI Frameworks SubTopic: SwiftUI
Replies
2
Boosts
2
Views
143
Activity
16h
Keyboard extensions and reserved regions
I have a keyboard extension in my app and I'm seeing some inconsistent behavior with the system-provided Globe and Dictation buttons. For the system keyboards, these buttons are displayed to the side of the keyboard, insetting the bottom row of keys on the folded screen and insetting the entire keyboard on the unfolded screen. What is the expected behavior for custom keyboards on the folded screen? My test results: When the Duo simulator is folded, sometimes the Globe and Dictation buttons appear next to my keyboard and the entire custom keyboard is squeezed to be really narrow. Other times my UI gets the full width and the Globe and Dictate keys are on TOP of my UI. The latter seems preferable, assuming I can then use the reserved regions API to avoid the overlap. Is that the intent? PS: The reserved regions API doesn't seem to work in keyboard extensions in this beta, neither in SwiftUI or UIKit. Hopefully that's fixed in the next beta.
Topic: UI Frameworks SubTopic: UIKit
Replies
1
Boosts
1
Views
63
Activity
17h
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
6
Boosts
9
Views
729
Activity
17h
Where do scroll indicators go on iPhone Duo?
In the process of updating an app for the iPhone Duo, I initially changed scroll/collection view leading/trailing to use the safe area. This puts the scroll indicators "inside" the side navigation bar: But looking at both Safari and Settings, the scroll indicators are placed "outside" the navigation bar: This leads to a couple of questions: Is the "outside" placement correct for a view with scrolling content? Is there a way to achieve this without reorganizing the scroll view content? The only solution I've found is to place a new container view inside a scroll view that uses the superview as its edge constraints. The container view gets placed using safe areas. If there's an easier way, I'd love to know what it is.
Topic: UI Frameworks SubTopic: UIKit
Replies
1
Boosts
1
Views
551
Activity
19h
Back button briefly jumps to the leading edge of the navigation bar during interactive pop from a screen with a hidden navigation bar (iPhone Duo)
On the iPhone Duo's narrow display, the navigation bar's back button sits in the trailing column below the status bar. During an interactive swipe-back from a screen whose navigation bar is hidden to a screen whose navigation bar is visible, the back button briefly renders in the leading (top-left) position of the bar for one or more frames. In those same frames the trailing-column button is blank. It then jumps back to the trailing column. The result is a visible flicker. Steps to reproduce: Open the attached code in Xcode 27.1 and run it on the iPhone Duo simulator (iOS 27.1), using the narrow display in portrait. Tap "Push". This pushes a screen with a visible navigation bar. Tap "Push without header". This pushes a screen that hides the navigation bar. Slowly swipe back from the leading edge to return to the previous screen. Expected: the back button of the revealed navigation bar stays in the trailing column for the whole transition, the same as with a programmatic pop. Actual: for one or more frames during the gesture, the back button renders at the leading edge of the navigation bar (top-left), and the trailing column is blank. Then it returns to the trailing column. Repro: import UIKit @main final class AppDelegate: UIResponder, UIApplicationDelegate {} final class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options: UIScene.ConnectionOptions) { guard let windowScene = scene as? UIWindowScene else { return } let window = UIWindow(windowScene: windowScene) let nav = SwipeableNavigationController(rootViewController: ScreenVC(title: "header 0", showsHeader: true)) window.rootViewController = nav window.makeKeyAndVisible() self.window = window // Auto sequence when launched with `-auto YES`: push header, push no header, pop. guard UserDefaults.standard.bool(forKey: "auto") else { return } DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { nav.pushViewController(ScreenVC(title: "header 0", showsHeader: true), animated: true) } DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) { nav.pushViewController(ScreenVC(title: "no header", showsHeader: false), animated: true) } DispatchQueue.main.asyncAfter(deadline: .now() + 4.5) { nav.popViewController(animated: true) } } } final class ScreenVC: UIViewController { private let showsHeader: Bool init(title: String, showsHeader: Bool) { self.showsHeader = showsHeader super.init(nibName: nil, bundle: nil) self.title = title } required init?(coder: NSCoder) { fatalError() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) navigationController?.setNavigationBarHidden(!showsHeader, animated: animated) } override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .systemGroupedBackground let push = UIButton(configuration: .plain(), primaryAction: UIAction(title: "Push") { [weak self] _ in self?.navigationController?.pushViewController(ScreenVC(title: "header 0", showsHeader: true), animated: true) }) let pushNoHeader = UIButton(configuration: .plain(), primaryAction: UIAction(title: "Push without header") { [weak self] _ in self?.navigationController?.pushViewController(ScreenVC(title: "no header", showsHeader: false), animated: true) }) let back = UIButton(configuration: .plain(), primaryAction: UIAction(title: "Go back") { [weak self] _ in self?.navigationController?.popViewController(animated: true) }) let stack = UIStackView(arrangedSubviews: [push, pushNoHeader, back]) stack.axis = .vertical stack.translatesAutoresizingMaskIntoConstraints = false view.addSubview(stack) NSLayoutConstraint.activate([ stack.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 10), stack.centerXAnchor.constraint(equalTo: view.centerXAnchor), ]) } } final class SwipeableNavigationController: UINavigationController, UIGestureRecognizerDelegate { override func viewDidLoad() { super.viewDidLoad() interactivePopGestureRecognizer?.delegate = self if #available(iOS 26.0, *) { interactiveContentPopGestureRecognizer?.delegate = self } } func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { viewControllers.count > 1 } } Thank you in advance!
Replies
1
Boosts
1
Views
203
Activity
23h
UISwitch's Liquid Glass toggle glow/shadow (iOS 26) is not clipped by a UIModalPresentationFormSheet / clipsToBounds container
Summary: On iOS 26, UISwitch has a Liquid Glass dynamic highlight/shadow effect that is not clipped by an ancestor view's bounds, even inside a UIModalPresentationFormSheet card. This is visible in two ways: (1) a plain tap on a switch positioned near the form sheet's edge already shows the highlight/shadow rendering outside the card's rounded border; (2) pressing and dragging the finger away from the switch drags this effect along with the touch, and it can end up rendered far outside the form sheet, well past the presentation area. Steps to Reproduce: Run the attached minimal project on an iOS 26 device/simulator. Tap "Present Form Sheet" to present a UIModalPresentationFormSheet containing a UITableView, with a UISwitch near the trailing edge of each row. Simply tap a switch near the sheet's edge — notice the dynamic highlight/shadow already overflows past the form sheet's rounded border. Now press and hold a switch, then quickly swipe/drag the finger downward (or in any direction) without lifting — notice the highlight/shadow follows the finger and gets dragged far outside the form sheet's bounds, over the dimmed presentation background. Expected Results: The Liquid Glass dynamic highlight/shadow effect should be clipped to the bounds of the form sheet card at all times, whether triggered by a plain tap or a drag gesture. Actual Results: On a plain tap near the edge: the highlight/shadow already overflows just past the form sheet's rounded border, unclipped. On press-and-drag: the highlight/shadow follows the finger and can be dragged far outside the form sheet — well beyond the card's edges and the presentation area. Configuration: iOS 26.x simulator/device Xcode 26.x // LiquidGlassSwitchDemo // // Minimal repro: UISwitch's Liquid Glass transition effect (iOS 26) is not // clipped by a UIModalPresentationFormSheet card, which clips everything else. // #import "AppDelegate.h" // Form sheet content: a table view full of UISwitch cells. @interface WMSwitchGlassCardViewController : UIViewController <UITableViewDataSource> @end @implementation WMSwitchGlassCardViewController - (void)viewDidLoad { [super viewDidLoad]; self.preferredContentSize = CGSizeMake(320, 400); UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleInsetGrouped]; tableView.dataSource = self; tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self.view addSubview:tableView]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 8; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]; cell.textLabel.text = [NSString stringWithFormat:@"Option %ld", (long)indexPath.row + 1]; UISwitch *toggle = [[UISwitch alloc] init]; toggle.on = YES; cell.accessoryView = toggle; // Actual: while toggling, the glass glow/shadow renders outside the form // sheet's rounded corners and floats over the dimmed background — the // card's clipsToBounds / rounded corners have no effect on the effect. return cell; } @end // Root screen: a single button that presents the card above as a form sheet. @interface WMRootViewController : UIViewController @end @implementation WMRootViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = UIColor.systemBackgroundColor; UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; [button setTitle:@"Present Form Sheet" forState:UIControlStateNormal]; [button addTarget:self action:@selector(presentCard) forControlEvents:UIControlEventTouchUpInside]; button.translatesAutoresizingMaskIntoConstraints = NO; [self.view addSubview:button]; [NSLayoutConstraint activateConstraints:@[ [button.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor], [button.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor], ]]; } - (void)presentCard { UIViewController *card = [WMSwitchGlassCardViewController new]; card.modalPresentationStyle = UIModalPresentationFormSheet; [self presentViewController:card animated:YES completion:nil]; } @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds]; self.window.rootViewController = [WMRootViewController new]; [self.window makeKeyAndVisible]; return YES; } @end```
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
0
Boosts
0
Views
190
Activity
1d
UISwitch's Liquid Glass toggle glow/shadow (iOS 26) is not clipped by a UIModalPresentationFormSheet / clipsToBounds container
Summary: On iOS 26, UISwitch has a Liquid Glass dynamic highlight/shadow effect that is not clipped by an ancestor view's bounds, even inside a UIModalPresentationFormSheet card. This is visible in two ways: (1) a plain tap on a switch positioned near the form sheet's edge already shows the highlight/shadow rendering outside the card's rounded border; (2) pressing and dragging the finger away from the switch drags this effect along with the touch, and it can end up rendered far outside the form sheet, well past the presentation area. Steps to Reproduce: Run the attached minimal project on an iOS 26 device/simulator. Tap "Present Form Sheet" to present a UIModalPresentationFormSheet containing a UITableView, with a UISwitch near the trailing edge of each row. Simply tap a switch near the sheet's edge — notice the dynamic highlight/shadow already overflows past the form sheet's rounded border. Now press and hold a switch, then quickly swipe/drag the finger downward (or in any direction) without lifting — notice the highlight/shadow follows the finger and gets dragged far outside the form sheet's bounds, over the dimmed presentation background. Expected Results: The Liquid Glass dynamic highlight/shadow effect should be clipped to the bounds of the form sheet card at all times, whether triggered by a plain tap or a drag gesture. Actual Results: On a plain tap near the edge: the highlight/shadow already overflows just past the form sheet's rounded border, unclipped. On press-and-drag: the highlight/shadow follows the finger and can be dragged far outside the form sheet — well beyond the card's edges and the presentation area. Configuration: iOS 26.x simulator/device Xcode 26.x // AppDelegate.m // LiquidGlassSwitchDemo // // Minimal repro: UISwitch's Liquid Glass transition effect (iOS 26) is not // clipped by a UIModalPresentationFormSheet card, which clips everything else. // #import "AppDelegate.h" // Form sheet content: a table view full of UISwitch cells. @interface WMSwitchGlassCardViewController : UIViewController <UITableViewDataSource> @end @implementation WMSwitchGlassCardViewController - (void)viewDidLoad { [super viewDidLoad]; self.preferredContentSize = CGSizeMake(320, 400); UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleInsetGrouped]; tableView.dataSource = self; tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self.view addSubview:tableView]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 8; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]; cell.textLabel.text = [NSString stringWithFormat:@"Option %ld", (long)indexPath.row + 1]; UISwitch *toggle = [[UISwitch alloc] init]; toggle.on = YES; cell.accessoryView = toggle; // Actual: while toggling, the glass glow/shadow renders outside the form // sheet's rounded corners and floats over the dimmed background — the // card's clipsToBounds / rounded corners have no effect on the effect. return cell; } @end // Root screen: a single button that presents the card above as a form sheet. @interface WMRootViewController : UIViewController @end @implementation WMRootViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = UIColor.systemBackgroundColor; UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; [button setTitle:@"Present Form Sheet" forState:UIControlStateNormal]; [button addTarget:self action:@selector(presentCard) forControlEvents:UIControlEventTouchUpInside]; button.translatesAutoresizingMaskIntoConstraints = NO; [self.view addSubview:button]; [NSLayoutConstraint activateConstraints:@[ [button.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor], [button.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor], ]]; } - (void)presentCard { UIViewController *card = [WMSwitchGlassCardViewController new]; card.modalPresentationStyle = UIModalPresentationFormSheet; [self presentViewController:card animated:YES completion:nil]; } @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds]; self.window.rootViewController = [WMRootViewController new]; [self.window makeKeyAndVisible]; return YES; } @end``` ![]("https://developer.apple.com/forums/content/attachment/3f8e87c4-d99f-4c03-adf8-b2c12a54aa8d" "title=20260928-151703@2x.png;width=666;height=644") ![]("https://developer.apple.com/forums/content/attachment/602ca9f8-c604-4168-9242-17d74c93b644" "title=20260928-151745@2x.png;width=544;height=396")
Replies
1
Boosts
0
Views
33
Activity
1d
There is a bug regarding CoreText.
When the end of the line is a Chinese symbol, it may appear that the rendering is based on the width of the visible content of the symbol, without considering the side bearing of the Chinese symbol, while the layout is calculated based on the full width of the Chinese symbol. The Chinese symbols should have been placed on the next line for rendering, but they ended up being partially placed on the previous line, resulting in a blank line below. Please refer to the Chinese exclamation mark in the attached image for details
Topic: UI Frameworks SubTopic: General
Replies
0
Boosts
0
Views
28
Activity
1d
Hinge listeners don't work in Keyboard Extension on iPhone Duo (iOS 27.1)
Hi, I've discovered that my Keyboard Extension is unable to detect any hinge status update on iPhone Duo. I tired both UIKit and SwiftUI approach - nothing works. Is there any workaround to make it work? Reproducible demo: https://www.icloud.com/iclouddrive/0460exMJtAdRkpk8EDjb751nw Xcode 27.1 (27A9269) iOS 27.1 beta 1 (24A94401) I also created a bug report: FB24883137
Replies
2
Boosts
1
Views
332
Activity
1d
iOS 27: UIApplication.shared.open fail for relative URL values that resolve to valid https URLs
A URL created with URL(string:relativeTo:) that used to work in iOS26 and below with UIApplication.shared.open stopped working in iOS27, the app has not been built yet with iOS27 SDK. Have anyone seen this issue, all the links work perfectly in iOS26 and below. We found a solution to use .absoluteURL but still want to check with the community, I havent seen any mention of this this that it will break try the below sample code import UIKit struct RelativeURLReproView: View { @State private var log = "Tap a button. Watch this log and whether Safari actually appears.\n" var body: some View { VStack(alignment: .leading, spacing: 16) { Button("Open relative URL") { openTarget(.relative) } .buttonStyle(.borderedProminent) Button("Open absoluteURL") { openTarget(.absolute) } .buttonStyle(.bordered) Button("Clear log") { log = "" } ScrollView { Text(log) .font(.system(.footnote, design: .monospaced)) .textSelection(.enabled) .frame(maxWidth: .infinity, alignment: .leading) } } .padding() } private enum ReproTarget { case relative case absolute } private func append(_ line: String) { log.append(line + "\n") print(line) } private func openTarget(_ target: ReproTarget) { log = "" let base = URL(string: "https://www.example.com")! let relative = URL(string: "about/help", relativeTo: base)! let url = (target == .relative) ? relative : relative.absoluteURL append("target: \(target == .relative ? "relative" : "absoluteURL")") append("url: \(url)") append("absoluteString: \(url.absoluteString)") append("scheme: \(url.scheme ?? "nil")") append("baseURL: \(url.baseURL?.absoluteString ?? "nil")") append("relativeString: \(url.relativeString)") append("canOpenURL: \(UIApplication.shared.canOpenURL(url))") append("Calling UIApplication.shared.open…") append("Did Safari actually appear? Check by eye.") UIApplication.shared.open(url, options: [:]) { success in Task { @MainActor in append("open completion: \(success)") } } } } #Preview { RelativeURLReproView() }
Replies
5
Boosts
0
Views
163
Activity
1d
Simple solution for visibilityPriority for toolbar items.
The iPhone Duo provides varying space for toolbar items based on screen orientation. One approach uses .visibilityPriority(_) to keep higher-priority items visible longer as the window shrinks and items go to the overflow menu. For instance: .toolbar { ToolbarItem { SecondaryControl() } ToolbarItem { PrimaryControl() } .visibilityPriority(.high) } The problem is that .visibilityPriority(_) requires iOS 27 or later, while typical apps aim for older systems such as iOS 26. What is your solution to keep the code simple?
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
4
Boosts
0
Views
86
Activity
1d
TimePicker numeric pad popover renders as a narrow bar on iPadOS 26.4.1
When tapping the currently selected time in a TimePicker (wheel style) component to invoke the inline numeric pad popover, the popover renders incorrectly on iPadOS 26.4.1 — it appears as a very narrow single-line/bar rather than the full numeric keypad layout. Steps to Reproduce: Run Reminder, create a new reminder and add a custom time Tap the currently selected time value to trigger the numeric pad popover Observe the popover layout Expected Result: A properly sized popover appears containing a full numeric keypad, allowing direct numeric input of the time value — consistent with behavior on iPadOS 18.x Actual Result: The popover appears as an extremely narrow horizontal bar (single line height), making the numeric pad unusable Regression: Works correctly on iPadOS 18.x through iPadOS 26.3. Broken on iPadOS 26.4.1 (Xcode 26.x simulator and/or physical device). https://www.youtube.com/shorts/bd3pYA3B-iI https://www.youtube.com/shorts/wSHzepHBwEY Feedback: FB22517457
Topic: UI Frameworks SubTopic: UIKit
Replies
6
Boosts
2
Views
1.1k
Activity
1d