Construct and manage graphical, event-driven user interfaces for iOS or tvOS apps using UIKit.

UIKit Documentation

Posts under UIKit subtopic

Post

Replies

Boosts

Views

Activity

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
39
10h
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
60
16h
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
213
17h
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
67
1d
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
593
1d
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
210
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 // 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
195
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
36
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
344
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
167
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
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
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
295
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
1
78
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
65
4d
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
51
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
90
4d
Bar layout guides are offset by the vertical-bar inset for views inside a UINavigationController when verticalBarEdge is leading
Configuration: Xcode 27.1 (27A9269) iOS 27.1 Simulator (24A94401), iPhone Duo macOS 27.2 (26B5086k) On iOS 27.1, when the vertical bar is on the leading edge, UINavigationController adds a leading safe area inset for the vertical bar (84 pt on iPhone Duo outer display) that the window itself does not have. Bar layout guides (UIView.layoutGuide(for: .bar(onEdge:extent:))) requested from any view inside the navigation controller are then resolved against that inset instead of the actual bar strip: Left-edge bar guides are pinned to x = 84 (the inner edge of the inset) instead of being centered in the vertical bar strip. Top/bottom bar guides start at x = 84. This part matches the mirrored trailing-edge behavior. The same guides requested from a view outside the navigation controller (the window's root view) put the left-edge guides correctly inside the strip, centered at x = 48. They are exact mirrors of the trailing-edge results. With the vertical bar on the trailing edge, everything is consistent: the window itself carries the 84 pt trailing inset and an active occlusion reserved region for the vertical status bar, and guides are identical whether requested from inside or outside the navigation controller. So the leading and trailing configurations are asymmetric. With a trailing bar, the vertical-bar inset lives on the window. With a leading bar, it exists only on UINavigationController's content, and the bar layout region math appears to treat it as an ordinary safe-area inset to avoid rather than as the bar strip. This happens with the navigation bar hidden via setNavigationBarHidden(true, animated: false). (Hiding it by setting navigationBar.isHidden = true additionally shifts the top guides down, which we assume is expected since the controller still considers the bar visible.) Steps to reproduce: Build and run the attached sample on the iPhone Duo simulator (iOS 27.1), outer display, portrait. Put the app in the configuration where traitCollection.verticalBarEdge == .leading. With "Plain root" selected, note the yellow (left-edge) bar guides: 22/44/88 pt bands share one center line inside the leading strip. Tap the center button and select "UINavigationController" (the navigation bar is hidden with setNavigationBarHidden(true, animated: false)). Observe the yellow bands and check the console output (lines prefixed with [BarLayoutGuidePlayground]). Repeat steps 3–5 with verticalBarEdge == .trailing and compare the green (right-edge) bands. Expected results: Bar layout guides resolve the same way for leading and trailing vertical bars, and the same way whether the requesting view is the window root or a child of UINavigationController. With a leading bar, the left-edge guides should be centered in the vertical bar strip (x = 37 / 26 / 4 for extents 22 / 44 / 88 in a 469 pt wide window), mirroring the trailing results (x = 410 / 399 / 377). Actual results: With a leading bar, inside UINavigationController: view.safeAreaInsets = (top: 0, left: 84, bottom: 34, right: 0) window.safeAreaInsets = (top: 0, left: 0, bottom: 34, right: 0) left 22: (84, 16, 22, 619) left 44: (84, 16, 44, 619) left 88: (84, 16, 88, 619) top 22: (84, 37, 376.33, 22) Same guides requested from the window's root view: left 22: (37, 16, 22, 619) left 44: (26, 16, 44, 619) left 88: (4, 16, 88, 619) top 22: (16, 37, 444.33, 22) With a trailing bar (identical from both views): view.safeAreaInsets = (top: 0, left: 0, bottom: 34, right: 84) window.safeAreaInsets = (top: 0, left: 0, bottom: 34, right: 84) occlusion reserved region (active): (385, 0, 84, 120) right 22: (410, 120, 22, 515) right 44: (399, 120, 44, 515) right 88: (377, 120, 88, 515) top 22: (8.67, 37, 376.33, 22) With a leading bar there is no active occlusion region for the status bar, and the window has no leading inset, yet UINavigationController adds one. Sample project
Topic: UI Frameworks SubTopic: UIKit
3
2
211
5d
Can a custom keyboard extend its background into the system-owned top and bottom area
Hello Apple Developer Community, I am developing Keyboard Atelier, a Korean custom keyboard built with Swift, UIKit, and UIInputViewController. Is there a supported way to apply a user-selected background color or image across the entire keyboard presentation, including the surrounding system-owned areas? Problem On an iPhone, we observe a strip above our keyboard extension’s visible content and a separate bottom area containing the system globe and dictation controls. When we apply a custom background to our extension, these surrounding areas retain a different background. This makes our keyboard look like a rectangular panel placed inside a separate system frame. Our product lets users customize keycaps and keyboard backgrounds. We want their selected color or image to appear continuous across the entire keyboard presentation. What we have tested We compared an opaque white root-view background with a clear root-view background in an isolated simulator test. With the opaque background, the boundaries above and below the extension were visible. Removing our own top padding did not eliminate the upper strip. Setting the root view’s backgroundColor to UIColor.clear made the backgrounds appear visually continuous in both light and dark appearances. However, this only reveals the default system background. It does not Questions Is there a public API or supported configuration that lets a custom keyboard specify the background color of the surrounding system-owned areas? Can a custom keyboard supply a background image that extends into those areas, including beneath the system globe and dictation controls? If neither is supported, what is the documented boundary of background customization for a keyboard extension? Is Feedback Assistant the appropriate place to request this capability? iOS should retain control of the system buttons, including their behavior, accessibility, touch targets, and contrast adjustments. We are asking to customize the background behind them while preserving their functionality. The solution must be suitable for App Store distribution and work when the keyboard is used in other apps, without requiring changes to those host apps. Reproduction steps Enable the custom keyboard in Settings > General > Keyboard > Keyboards. Open a UITextView in the containing app. Switch to the custom keyboard. Set the keyboard extension’s root-view background to an opaque white color while using dark appearance. Observe the different backgrounds above and below the extension’s content. Compare this with a build using UIColor.clear for the root-view background. Implementation Swift and UIKit UIInputViewController keyboard extension Test host: a UIKit UITextView in the containing app Light and dark appearances tested RequestsOpenAccess = false Please point me to any relevant API or documentation, or clarify whether this would require a new API. Thank you.
Topic: UI Frameworks SubTopic: UIKit
0
0
61
5d
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
39
Activity
10h
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
60
Activity
16h
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
213
Activity
17h
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
67
Activity
1d
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
593
Activity
1d
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
210
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 // 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
195
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
36
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
344
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
167
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
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
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
295
Activity
2d
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
353
Activity
3d
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
1
Views
78
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
65
Activity
4d
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
51
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
90
Activity
4d
Bar layout guides are offset by the vertical-bar inset for views inside a UINavigationController when verticalBarEdge is leading
Configuration: Xcode 27.1 (27A9269) iOS 27.1 Simulator (24A94401), iPhone Duo macOS 27.2 (26B5086k) On iOS 27.1, when the vertical bar is on the leading edge, UINavigationController adds a leading safe area inset for the vertical bar (84 pt on iPhone Duo outer display) that the window itself does not have. Bar layout guides (UIView.layoutGuide(for: .bar(onEdge:extent:))) requested from any view inside the navigation controller are then resolved against that inset instead of the actual bar strip: Left-edge bar guides are pinned to x = 84 (the inner edge of the inset) instead of being centered in the vertical bar strip. Top/bottom bar guides start at x = 84. This part matches the mirrored trailing-edge behavior. The same guides requested from a view outside the navigation controller (the window's root view) put the left-edge guides correctly inside the strip, centered at x = 48. They are exact mirrors of the trailing-edge results. With the vertical bar on the trailing edge, everything is consistent: the window itself carries the 84 pt trailing inset and an active occlusion reserved region for the vertical status bar, and guides are identical whether requested from inside or outside the navigation controller. So the leading and trailing configurations are asymmetric. With a trailing bar, the vertical-bar inset lives on the window. With a leading bar, it exists only on UINavigationController's content, and the bar layout region math appears to treat it as an ordinary safe-area inset to avoid rather than as the bar strip. This happens with the navigation bar hidden via setNavigationBarHidden(true, animated: false). (Hiding it by setting navigationBar.isHidden = true additionally shifts the top guides down, which we assume is expected since the controller still considers the bar visible.) Steps to reproduce: Build and run the attached sample on the iPhone Duo simulator (iOS 27.1), outer display, portrait. Put the app in the configuration where traitCollection.verticalBarEdge == .leading. With "Plain root" selected, note the yellow (left-edge) bar guides: 22/44/88 pt bands share one center line inside the leading strip. Tap the center button and select "UINavigationController" (the navigation bar is hidden with setNavigationBarHidden(true, animated: false)). Observe the yellow bands and check the console output (lines prefixed with [BarLayoutGuidePlayground]). Repeat steps 3–5 with verticalBarEdge == .trailing and compare the green (right-edge) bands. Expected results: Bar layout guides resolve the same way for leading and trailing vertical bars, and the same way whether the requesting view is the window root or a child of UINavigationController. With a leading bar, the left-edge guides should be centered in the vertical bar strip (x = 37 / 26 / 4 for extents 22 / 44 / 88 in a 469 pt wide window), mirroring the trailing results (x = 410 / 399 / 377). Actual results: With a leading bar, inside UINavigationController: view.safeAreaInsets = (top: 0, left: 84, bottom: 34, right: 0) window.safeAreaInsets = (top: 0, left: 0, bottom: 34, right: 0) left 22: (84, 16, 22, 619) left 44: (84, 16, 44, 619) left 88: (84, 16, 88, 619) top 22: (84, 37, 376.33, 22) Same guides requested from the window's root view: left 22: (37, 16, 22, 619) left 44: (26, 16, 44, 619) left 88: (4, 16, 88, 619) top 22: (16, 37, 444.33, 22) With a trailing bar (identical from both views): view.safeAreaInsets = (top: 0, left: 0, bottom: 34, right: 84) window.safeAreaInsets = (top: 0, left: 0, bottom: 34, right: 84) occlusion reserved region (active): (385, 0, 84, 120) right 22: (410, 120, 22, 515) right 44: (399, 120, 44, 515) right 88: (377, 120, 88, 515) top 22: (8.67, 37, 376.33, 22) With a leading bar there is no active occlusion region for the status bar, and the window has no leading inset, yet UINavigationController adds one. Sample project
Topic: UI Frameworks SubTopic: UIKit
Replies
3
Boosts
2
Views
211
Activity
5d
Can a custom keyboard extend its background into the system-owned top and bottom area
Hello Apple Developer Community, I am developing Keyboard Atelier, a Korean custom keyboard built with Swift, UIKit, and UIInputViewController. Is there a supported way to apply a user-selected background color or image across the entire keyboard presentation, including the surrounding system-owned areas? Problem On an iPhone, we observe a strip above our keyboard extension’s visible content and a separate bottom area containing the system globe and dictation controls. When we apply a custom background to our extension, these surrounding areas retain a different background. This makes our keyboard look like a rectangular panel placed inside a separate system frame. Our product lets users customize keycaps and keyboard backgrounds. We want their selected color or image to appear continuous across the entire keyboard presentation. What we have tested We compared an opaque white root-view background with a clear root-view background in an isolated simulator test. With the opaque background, the boundaries above and below the extension were visible. Removing our own top padding did not eliminate the upper strip. Setting the root view’s backgroundColor to UIColor.clear made the backgrounds appear visually continuous in both light and dark appearances. However, this only reveals the default system background. It does not Questions Is there a public API or supported configuration that lets a custom keyboard specify the background color of the surrounding system-owned areas? Can a custom keyboard supply a background image that extends into those areas, including beneath the system globe and dictation controls? If neither is supported, what is the documented boundary of background customization for a keyboard extension? Is Feedback Assistant the appropriate place to request this capability? iOS should retain control of the system buttons, including their behavior, accessibility, touch targets, and contrast adjustments. We are asking to customize the background behind them while preserving their functionality. The solution must be suitable for App Store distribution and work when the keyboard is used in other apps, without requiring changes to those host apps. Reproduction steps Enable the custom keyboard in Settings > General > Keyboard > Keyboards. Open a UITextView in the containing app. Switch to the custom keyboard. Set the keyboard extension’s root-view background to an opaque white color while using dark appearance. Observe the different backgrounds above and below the extension’s content. Compare this with a build using UIColor.clear for the root-view background. Implementation Swift and UIKit UIInputViewController keyboard extension Test host: a UIKit UITextView in the containing app Light and dark appearances tested RequestsOpenAccess = false Please point me to any relevant API or documentation, or clarify whether this would require a new API. Thank you.
Topic: UI Frameworks SubTopic: UIKit
Replies
0
Boosts
0
Views
61
Activity
5d