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

Posts under UIKit tag

200 Posts

Post

Replies

Boosts

Views

Activity

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
5h
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
200
21h
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
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 // 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
23h
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
329
23h
iOS 27: ScrollViewProxy.scrollTo no longer reaches unrealized LazyVStack rows; how to preserve position when prepending?
I have a chat screen built with ScrollView { LazyVStack } and ScrollViewReader. Two things that worked through iOS 26 stopped working on iOS 27 (Xcode 27, iOS 27.0 simulator and device; unchanged code still works on the iOS 26.x simulator): Open at the newest message. On appear I call proxy.scrollTo(lastId, anchor: .bottom). On iOS 27 the list stops two or three rows above the bottom when the rows have variable heights (text bubbles mixed with 200pt images). Load older messages at the top without the list jumping. When the user reaches the top, I prepend 25 older messages and call proxy.scrollTo(previousTopId, anchor: .top) so the row they were reading stays put. On iOS 27 the call does nothing: the list stays at the top of the newly inserted page (offset stays at 0), which immediately re-triggers the load. Re-issuing scrollTo on every layout change for a short window (which is what made this reliable on iOS 26) has no effect on iOS 27. Minimal reproduction import SwiftUI struct Message: Identifiable, Hashable { let id: Int let height: CGFloat // simulates text vs. image bubbles } @MainActor final class ChatModel: ObservableObject { @Published var messages: [Message] = [] @Published var previousTopId: Int? // set when a page is prepended private var nextOldId = 1_000 init() { messages = (0..<25).map { Message(id: nextOldId - $0, height: Self.randomHeight()) }.reversed() nextOldId -= 25 } func loadOlder() { let top = messages.first!.id let page = (0..<25).map { Message(id: nextOldId - $0, height: Self.randomHeight()) }.reversed() nextOldId -= 25 messages.insert(contentsOf: page, at: 0) previousTopId = top // "keep this row at the top" } static func randomHeight() -> CGFloat { [44, 60, 90, 200, 260].randomElement()! } } struct ChatView: View { @StateObject private var model = ChatModel() var body: some View { ScrollViewReader { proxy in ScrollView { LazyVStack(spacing: 8) { // top sentinel: load older when it becomes visible Color.clear.frame(height: 1) .onAppear { model.loadOlder() } ForEach(model.messages) { m in RoundedRectangle(cornerRadius: 12) .fill(m.height >= 200 ? .orange.opacity(0.4) : .blue.opacity(0.3)) .frame(height: m.height) .overlay(Text("\(m.id)")) .padding(.horizontal) .id(m.id) } } } .onAppear { // (1) open at the newest message DispatchQueue.main.async { proxy.scrollTo(model.messages.last!.id, anchor: .bottom) } } .onChange(of: model.previousTopId) { _, id in // (2) restore the row that was at the top before the prepend guard let id else { return } DispatchQueue.main.async { var t = Transaction(); t.disablesAnimations = true withTransaction(t) { proxy.scrollTo(id, anchor: .top) } } } } } } Observed (1) Open at the newest message, scrollTo(lastId, anchor: .bottom) iOS 26.x: lands on the last row. iOS 27.0: stops 2–3 rows above the bottom. (2) Prepend 25 rows, then scrollTo(previousTopId, anchor: .top) iOS 26.x: the previous top row is at the top of the viewport. iOS 27.0: the offset stays at 0 and the new page's first row is at the top. What I have tried on iOS 27 Re-issuing scrollTo for 0.5s on every content-height or offset change (via GeometryReader preferences). No effect; the target row is not realized, and the visible rows are kept stable instead. .defaultScrollAnchor(.bottom) and .defaultScrollAnchor(.bottom, for: .sizeChanges): fixes the initial open, but the stored anchor is re-applied once on the first content change (the prepend), which snaps the list to the newest message. .sizeChanges did not preserve the prepend. .scrollPosition(id: $topId, anchor: .top) with .scrollTargetLayout() on the LazyVStack: the binding tracks the top row correctly, but after the prepend SwiftUI re-targets the binding to the new page's first row. Writing the previous id back, in the same update or on later run-loop turns, does not restore the position. Replacing LazyVStack with VStack fixes both cases, but the list holds hundreds of image rows and needs the lazy container for memory. What does work: reaching the backing UIScrollView (SwiftUIIntrospect), recording the visible rows' frames before the insert and adjusting contentOffset after layout. It works but is a lot of code for something that used to be one scrollTo. Questions Is it intended on iOS 27 that ScrollViewProxy.scrollTo does not scroll to a LazyVStack row that is not currently realized, or that the lazy stack keeps the currently visible rows stable in preference to the requested target? The WWDC26 lazy-stacks session describes the stack and scroll view coordinating the offset as estimates update; is scrollTo to an unrealized row now unsupported? Is there a supported SwiftUI way on iOS 27 to keep the visible rows in place when items are prepended to a LazyVStack, or to scroll reliably to an unrealized row? For example a ScrollPosition usage or an anchor role I am missing. If not, is adjusting the UIScrollView offset the expected approach, or is List now the recommended container for chat-style lists with bidirectional paging? I have filed this as FB24968838 with the sample project attached.
0
0
56
1d
UINavigationBarAppearance background does not extend to the top edge on iPhone Duo
Environment Xcode 27.1 iOS 27.1 iPhone Duo simulator UIKit app built with the iOS 27.1 SDK Issue On iPhone Duo, the background of a system-managed UINavigationBar does not extend completely to the top edge of the window. The navigation bar is configured using UINavigationBarAppearance with an opaque blue background. However, a horizontal white strip remains above the blue navigation bar. I also post a feedback: FB24859353 Questions Is this expected behavior on iPhone Duo? What is the recommended way to style this top region? Should apps add a custom background underlay outside the UINavigationBar bounds? Could this be an iOS 27.1 or iPhone Duo simulator issue? Minimal reproduction code: import UIKit final class DemoTabBarController: UITabBarController { override func viewDidLoad() { super.viewDidLoad() viewControllers = NavigationBarStyle.allCases.map { style in let content = DiagnosticsViewController(style: style) let navigationController = UINavigationController(rootViewController: content) navigationController.tabBarItem = UITabBarItem( title: style.title, image: UIImage(systemName: style.symbolName), selectedImage: nil ) style.apply(to: navigationController.navigationBar) return navigationController } } } enum NavigationBarStyle: CaseIterable { case systemDefault case appearance case legacy var title: String { switch self { case .systemDefault: return "Default" case .appearance: return "Appearance" case .legacy: return "Legacy" } } var symbolName: String { switch self { case .systemDefault: return "iphone" case .appearance: return "paintbrush" case .legacy: return "clock.arrow.circlepath" } } func apply(to navigationBar: UINavigationBar) { switch self { case .systemDefault: break case .appearance: let appearance = UINavigationBarAppearance() appearance.configureWithOpaqueBackground() appearance.backgroundColor = .demoBlue appearance.shadowColor = nil appearance.titleTextAttributes = [.foregroundColor: UIColor.white] navigationBar.tintColor = .white navigationBar.standardAppearance = appearance navigationBar.compactAppearance = appearance navigationBar.scrollEdgeAppearance = appearance case .legacy: navigationBar.tintColor = .white navigationBar.barTintColor = .demoBlue navigationBar.backgroundColor = .demoBlue navigationBar.setBackgroundImage(Self.solidImage(color: .demoBlue), for: .default) navigationBar.shadowImage = UIImage() navigationBar.isTranslucent = false navigationBar.titleTextAttributes = [.foregroundColor: UIColor.white] } } private static func solidImage(color: UIColor) -> UIImage { return UIGraphicsImageRenderer(size: CGSize(width: 1, height: 1)).image { context in color.setFill() context.fill(CGRect(x: 0, y: 0, width: 1, height: 1)) } } } private extension UIColor { static let demoBlue = UIColor(red: 0.0, green: 0.46, blue: 0.70, alpha: 1.0) }
2
1
292
1d
How to check for multiple scene support on iPhone Duo?
I have an iOS app that supports multiple scenes on the iPad, and which has an "Open in Another Window" feature which creates a new window scene. I would like to bring this feature to the iPhone Duo. On the iPhone Duo, of course, creating new windows is only supported when the device is open; when it is closed, creating new windows does not work. (If you try, an error is thrown.) Until now, the way I have checked whether my "Open in Another Window" feature should be available is to check to see if UIApplication.shared.supportsMultipleScenes is true. This has always returned false for previous iPhones and true for iPads. Unfortunately, however, this does not work as expected on the iPhone Duo. On the Duo, I would expect supportsMultipleScenes to return true when the device is open, but false when it is closed. This is not the case: it returns true for all poses. (Filed as #FB24948411 as this doesn't seem right to me.) So it does not help me decide whether the feature should be available. UIWindowScene.ActivationAction does work as expected when used in a menu, with the action auto-hiding when the Duo is in the closed pose. In my app, though, I need more than just an auto-hiding menu item; I need to check whether creating a new window is currently possible for certain UI availability decisions. What, then, is the correct way of checking this, if it's not with supportsMultipleScenes? Given that UIWindowScene.ActivationAction is able to hide itself, I assume there is some better way of checking that I have missed.
Topic: UI Frameworks SubTopic: UIKit Tags:
0
0
70
2d
SplitViewController removed the ability to have a side menu on iPhone
Sometime pre-iOS 26 it was possible to use a SplitViewController so that on iPhone you saw the master as a side menu (e.g. hamburger), and the detail full screen. While on iPad you would see the master displayed in a sidebar that could be closed, with the detail fullscreen. This has changed, using a SplitViewController on iPhone now forces you into having 2 fullscreen screens, with a push/pop layout and a back button. In situations where you want the detail screen to open first, this results in users opening the app to find a back button already presented, despite having not navigated anywhere. They must "return" to a screen they never saw. I really despise this layout and find it to be quite a UX issue. But given the new iPhone Duo, using the SplitViewController is now one of the easiest ways to maintain the necessary responsiveness needed, forcing us to accept this behaviour on regular iPhones. Can we PLEASE get the old functionality back, where we can explicitly state on iPhone that the master will always be displayed as a menu?
0
0
81
4d
Stale blur glass effect appears at top of UITableView and WKWebView after user updates device to iOS 27, app built with Xcode 26.3
Environment App built with Xcode 26.3 (iOS 26 SDK) Deployment Target: iOS 16+ Issue occurs only on devices upgraded to iOS 27. Works perfectly on iOS 26.x. Problem description: After end‑user upgrades their iPhone to iOS 27, a persistent stale frosted‑glass / blur rendering effect appears at the top area of screens. This symptom occurs both on native UITableView and inside WKWebView. No blur‑related code (UIVisualEffectView / backdrop‑filter) is added by our application. Layout frames, insets and contentOffset are all correct. Reproduction hints: The issue can be triggered after presenting then dismissing a WKWebView which loads H5 with overlay popup. Rendering state seems to leak to the whole app process. The leftover blur remains until push/pop the view controller. Is this an iOS 27 system bug, or do we need special adaptation for existing apps built with older Xcode 26.3 SDK? What is the proper workaround for apps compiled with Xcode26.3, since liquidGlassEffectEnabled is only available in iOS27 SDK and cannot be accessed in our current build environment.
5
0
423
4d
Custom UIPresentationController cannot match iPhone Duo sheet vertical-bar behavior
Tested on iPhone Duo with iOS 27.1 in Xcode 27.1 Beta Presented VC returns .disabled from preferredVerticalBarBehavior. With UISheetPresentationController, the sheet's trailing safe-area inset is removed at all detents (including default medium and large, plus custom detents at various fixed heights). The interesting part: the status bar remains in the vertical bar for detents below UISheetPresentationControllerDetentResolutionContext.maximumDetentValue, but at detents that are greater than or equal to that maximumDetentValue, the status bar moves to the top. With a custom UIPresentationController: Default shouldPresentInFullscreen == true: trailing inset remains, regardless of presented VC's preferredVerticalBarBehavior (possibly expected) With shouldPresentInFullscreen == false: trailing inset is removed, but the status bar moves to the top regardless of the presented view's height. Using automatic as preferredVerticalBarBehavior keeps the status bar on the right, but also keeps the safe-area insets increased. Is UISheetPresentationController applying detent-aware, presentation-scoped vertical bar behavior? Is there a public way for a custom UIPresentationController to remove the sheet's vertical-bar inset while keeping the status bar vertical [until the presentation reaches full height]?
0
0
74
5d
Tapping the top area of iPhone Duo does not respond in Device Hub
I’m simulating an iPhone Duo using Xcode 27.1 beta, and I’m having trouble tapping buttons placed near the top of the screen. It seems that the top ~20 pixels of the screen are not responding to taps. In my ViewController, preferredScreenEdgesDeferringSystemGestures returns .all, so system gestures should require two swipes to be triggered. However, a simple tap in this area does not seem to be recognized. This appears to happen only on iPhone Duo; taps work normally on other iPhone models. Does anyone know whether this behavior is expected to occur on the actual iPhone Duo hardware as well, or is it specific to the simulator? For reference, the buttons are positioned according to LayoutMarginsGuide with Safe Area. FB24914903 I wonder if anyone knows how to get the top margin size programmatically.
0
0
88
5d
Finger input interrupted while drawing with Apple Pencil + palm resting on display
I’m investigating an issue with simultaneous Apple Pencil and finger input on iPad. Apple Pencil + finger input works correctly while the Pencil user’s hand/palm is off the display. However, when drawing naturally with Apple Pencil with the palm resting on the display, an existing finger drawing contact elsewhere on the screen can be cancelled and then stop receiving input for several seconds. Pencil input continues normally throughout. Initially I suspected PencilKit, but I’ve reproduced the underlying behaviour below PencilKit/SwiftUI. Instrumenting UIKit at UIApplication.sendEvent shows the finger touch being cancelled and, in some cases, no further events for that finger for ~4–5 seconds while Pencil MOVED events continue to arrive normally. Everything delivered to the application is accounted for, so this appears to occur before our drawing/rendering code. Is this expected behaviour from the iPad’s Pencil/palm rejection? More specifically: Is there any supported way to tell UIKit that an existing finger contact should remain intentional while Pencil + palm contact is present? Is palm rejection configurable at this level? Is there another public input API we should be using for this scenario? We’re currently testing UIEvent.coalescedTouches(for:) to determine whether additional genuine finger samples are available during these apparent gaps, but haven’t completed that test yet. Any guidance on whether this interaction is expected to be supportable through public UIKit APIs would be appreciated.
1
0
311
5d
UndoManager access from Keyboard extension
Hi,I'm trying to implement undo and redo, in a Custom keyboard extension. However, calling undo() on the UndoManager from UIInputViewController, doesn't seems to work. Is there any other way of getting the UndoManager from the app the keyboard is connected to?Or do I need create my own logic to store what a user has written?
Topic: UI Frameworks SubTopic: UIKit Tags:
1
1
385
5d
Best Practice to adopt iPhone Duo
What's the best practices to adopt iPhone Duo for a production UIKit app? What few things we need to consider during the development? "As long as we use auto layout, it should be fine" is this correct term for iPhone Duo? Meaning, as long as our app use proper auto layout, our app should be able to support iPhone Duo properly.
0
0
61
5d
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
UITableView behavior on iPhone Duo
I’m adapting a UIKit app for iPhone Duo and noticed that UITableViewController separators extend underneath the navigation and tab bar controls when those controls move to the side. The cell content appears to respect the safe area, but the separators continue to the screen edge. When using a UITableView inside a regular UIViewController, constraining its horizontal edges to the parent’s safeAreaLayoutGuide prevents this. With UITableViewController, however, the table view is the controller’s root view. The attached screenshots show the difference: Screenshot 1: Separators extend underneath the side controls. Screenshot 2: Separators stop at the safe area boundary. Should UITableViewController respect these safe area boundaries out of the box, including for separators, when system controls move to the side? Or is drawing separators underneath those controls the intended behavior? If automatic adaptation is expected, could this be a UIKit issue?
0
0
95
6d
UIAlertController.addTextField results in broken text field in 27.1
I just downloaded Xcode 27.1 to test out the iPhone Duo simulator, and I notice that UIAlertController.addTextField, which was working fine in 27, is now very broken, resulting in a text field that is squashed vertically and pushed over to the right in the alert sheet. This is very easy to reproduce - the following code will show the problem if you build in Xcode 27.1 and run on iOS 27.1 or iOS 27.2: let alert = UIAlertController(title: "Create Something", message: "Enter a title.", preferredStyle: .alert) alert.addTextField { textField in textField.placeholder = "Title" } alert.addAction(UIAlertAction(title: "Cancel", style: .cancel)) present(alert, animated: true) The bug isn't limited to the Duo, but can also be seen on an iPad (and probably a regular phone). I would post a screenshot, but the last time I tried that, the forum software erroneously banned me for two weeks. I have reported this as bug #FB24889500, but given that we use alerts with text fields for users adding new items to the outline in our app, something the user does a lot, I'm wondering if there is a workaround, since this is going to make our app look very buggy.
Topic: UI Frameworks SubTopic: UIKit Tags:
0
0
76
1w
System permission alerts mis‑positioned for AppDelegate‑only legacy UIKit app on iPhone Duo (Xcode26 / iOS26 SDK)
Hi everyone, We are validating our existing legacy UIKit application on iPhone Duo, built using Xcode26 and the iOS26 SDK. Our app follows the classic AppDelegate‑only pattern. We do not adopt UIApplicationSceneManifest or SceneDelegate, so it runs under the system’s legacy compatibility container window. The codebase still heavily uses UIScreen.main, and we have not yet adopted UIWindowScene. Full scene‑based migration is planned for Xcode27, but we need to ship builds with Xcode26 for now and expect reasonable compatibility on iPhone Duo hardware. Most of our application UI displays correctly inside this system‑provided compatibility window. However we noticed a critical positioning defect for system‑owned permission alerts. System‑rendered authorization dialogs (push notification permission, photo library access, location permission — these are drawn by the system process, not our app) are positioned relative to the full physical inner display of iPhone Duo. Instead of centering within our app’s compatibility‑mode container viewport, these permission pop‑ups appear offset and misaligned against our app’s visible window bounds. I have three key questions: Is this mis‑positioning of system permission alerts expected documented behavior for non‑Scene, AppDelegate‑only legacy apps running inside compatibility mode on iPhone Duo when built with Xcode26 SDK? While we remain on Xcode26 SDK, before completing full scene‑based lifecycle migration for Xcode27: are there any known workarounds to correct or mitigate this system permission alert offset issue? Or is this a hard limitation of the legacy compatibility mode in Xcode26, meaning we cannot fix it until we fully migrate to scene‑based app lifecycle? If this is intended limitation, could anyone point me to official Apple documentation that covers this exact behavior for legacy apps on iPhone Duo? Thanks for any insight.
0
0
238
1w
UISheetPresentationController issues on iPhone Duo
I have an App where I use the UISheetPresentationController to present a menu as a "drawer" (like the "FindMy" or "Maps") App. Because the sheet is presented over a map, I made the sheet semi-transparent/blurry, so the Map shines through, which looks nice. The sheet is using a UITableView with the "insetGroup" style, so the table cells have the nice rounded borders and there are margins to the sheet borders. When running the App on the iPhone Duo (Simulator) on the outer display, the tableView does no longer respect the "insetGroup" style, it is rendered like it would have the "plain" style, which destroys everything that look good. No rounded borders, no margins. However if I opt-out of the automatic "vertical toolbar behavior" (overriding preferredVerticalBarBehavior so it returns "disabled"), then everything looks great again, however then the sheet content might overlap with the sidebar icons and camera because it now covers the whole area up to the right screen border. Is this supposed to be this way (if yes, why?), is there a way to fix this, or do we have to wait for a bugfix within iOS 27.1? The tableview still claims to have the "insetGrouped" style, just it does not render this way. I did not see any similar issues under other circumstances. Only UISheetPresentationController seems to be affected by this. Is there a way to correctly detect if the App is running on an iPhone Duo, so we could use this detection to add workarounds for such issues?
1
0
201
1w
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
5h
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
200
Activity
21h
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
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 // 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
23h
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
329
Activity
23h
iOS 27: ScrollViewProxy.scrollTo no longer reaches unrealized LazyVStack rows; how to preserve position when prepending?
I have a chat screen built with ScrollView { LazyVStack } and ScrollViewReader. Two things that worked through iOS 26 stopped working on iOS 27 (Xcode 27, iOS 27.0 simulator and device; unchanged code still works on the iOS 26.x simulator): Open at the newest message. On appear I call proxy.scrollTo(lastId, anchor: .bottom). On iOS 27 the list stops two or three rows above the bottom when the rows have variable heights (text bubbles mixed with 200pt images). Load older messages at the top without the list jumping. When the user reaches the top, I prepend 25 older messages and call proxy.scrollTo(previousTopId, anchor: .top) so the row they were reading stays put. On iOS 27 the call does nothing: the list stays at the top of the newly inserted page (offset stays at 0), which immediately re-triggers the load. Re-issuing scrollTo on every layout change for a short window (which is what made this reliable on iOS 26) has no effect on iOS 27. Minimal reproduction import SwiftUI struct Message: Identifiable, Hashable { let id: Int let height: CGFloat // simulates text vs. image bubbles } @MainActor final class ChatModel: ObservableObject { @Published var messages: [Message] = [] @Published var previousTopId: Int? // set when a page is prepended private var nextOldId = 1_000 init() { messages = (0..<25).map { Message(id: nextOldId - $0, height: Self.randomHeight()) }.reversed() nextOldId -= 25 } func loadOlder() { let top = messages.first!.id let page = (0..<25).map { Message(id: nextOldId - $0, height: Self.randomHeight()) }.reversed() nextOldId -= 25 messages.insert(contentsOf: page, at: 0) previousTopId = top // "keep this row at the top" } static func randomHeight() -> CGFloat { [44, 60, 90, 200, 260].randomElement()! } } struct ChatView: View { @StateObject private var model = ChatModel() var body: some View { ScrollViewReader { proxy in ScrollView { LazyVStack(spacing: 8) { // top sentinel: load older when it becomes visible Color.clear.frame(height: 1) .onAppear { model.loadOlder() } ForEach(model.messages) { m in RoundedRectangle(cornerRadius: 12) .fill(m.height >= 200 ? .orange.opacity(0.4) : .blue.opacity(0.3)) .frame(height: m.height) .overlay(Text("\(m.id)")) .padding(.horizontal) .id(m.id) } } } .onAppear { // (1) open at the newest message DispatchQueue.main.async { proxy.scrollTo(model.messages.last!.id, anchor: .bottom) } } .onChange(of: model.previousTopId) { _, id in // (2) restore the row that was at the top before the prepend guard let id else { return } DispatchQueue.main.async { var t = Transaction(); t.disablesAnimations = true withTransaction(t) { proxy.scrollTo(id, anchor: .top) } } } } } } Observed (1) Open at the newest message, scrollTo(lastId, anchor: .bottom) iOS 26.x: lands on the last row. iOS 27.0: stops 2–3 rows above the bottom. (2) Prepend 25 rows, then scrollTo(previousTopId, anchor: .top) iOS 26.x: the previous top row is at the top of the viewport. iOS 27.0: the offset stays at 0 and the new page's first row is at the top. What I have tried on iOS 27 Re-issuing scrollTo for 0.5s on every content-height or offset change (via GeometryReader preferences). No effect; the target row is not realized, and the visible rows are kept stable instead. .defaultScrollAnchor(.bottom) and .defaultScrollAnchor(.bottom, for: .sizeChanges): fixes the initial open, but the stored anchor is re-applied once on the first content change (the prepend), which snaps the list to the newest message. .sizeChanges did not preserve the prepend. .scrollPosition(id: $topId, anchor: .top) with .scrollTargetLayout() on the LazyVStack: the binding tracks the top row correctly, but after the prepend SwiftUI re-targets the binding to the new page's first row. Writing the previous id back, in the same update or on later run-loop turns, does not restore the position. Replacing LazyVStack with VStack fixes both cases, but the list holds hundreds of image rows and needs the lazy container for memory. What does work: reaching the backing UIScrollView (SwiftUIIntrospect), recording the visible rows' frames before the insert and adjusting contentOffset after layout. It works but is a lot of code for something that used to be one scrollTo. Questions Is it intended on iOS 27 that ScrollViewProxy.scrollTo does not scroll to a LazyVStack row that is not currently realized, or that the lazy stack keeps the currently visible rows stable in preference to the requested target? The WWDC26 lazy-stacks session describes the stack and scroll view coordinating the offset as estimates update; is scrollTo to an unrealized row now unsupported? Is there a supported SwiftUI way on iOS 27 to keep the visible rows in place when items are prepended to a LazyVStack, or to scroll reliably to an unrealized row? For example a ScrollPosition usage or an anchor role I am missing. If not, is adjusting the UIScrollView offset the expected approach, or is List now the recommended container for chat-style lists with bidirectional paging? I have filed this as FB24968838 with the sample project attached.
Replies
0
Boosts
0
Views
56
Activity
1d
UINavigationBarAppearance background does not extend to the top edge on iPhone Duo
Environment Xcode 27.1 iOS 27.1 iPhone Duo simulator UIKit app built with the iOS 27.1 SDK Issue On iPhone Duo, the background of a system-managed UINavigationBar does not extend completely to the top edge of the window. The navigation bar is configured using UINavigationBarAppearance with an opaque blue background. However, a horizontal white strip remains above the blue navigation bar. I also post a feedback: FB24859353 Questions Is this expected behavior on iPhone Duo? What is the recommended way to style this top region? Should apps add a custom background underlay outside the UINavigationBar bounds? Could this be an iOS 27.1 or iPhone Duo simulator issue? Minimal reproduction code: import UIKit final class DemoTabBarController: UITabBarController { override func viewDidLoad() { super.viewDidLoad() viewControllers = NavigationBarStyle.allCases.map { style in let content = DiagnosticsViewController(style: style) let navigationController = UINavigationController(rootViewController: content) navigationController.tabBarItem = UITabBarItem( title: style.title, image: UIImage(systemName: style.symbolName), selectedImage: nil ) style.apply(to: navigationController.navigationBar) return navigationController } } } enum NavigationBarStyle: CaseIterable { case systemDefault case appearance case legacy var title: String { switch self { case .systemDefault: return "Default" case .appearance: return "Appearance" case .legacy: return "Legacy" } } var symbolName: String { switch self { case .systemDefault: return "iphone" case .appearance: return "paintbrush" case .legacy: return "clock.arrow.circlepath" } } func apply(to navigationBar: UINavigationBar) { switch self { case .systemDefault: break case .appearance: let appearance = UINavigationBarAppearance() appearance.configureWithOpaqueBackground() appearance.backgroundColor = .demoBlue appearance.shadowColor = nil appearance.titleTextAttributes = [.foregroundColor: UIColor.white] navigationBar.tintColor = .white navigationBar.standardAppearance = appearance navigationBar.compactAppearance = appearance navigationBar.scrollEdgeAppearance = appearance case .legacy: navigationBar.tintColor = .white navigationBar.barTintColor = .demoBlue navigationBar.backgroundColor = .demoBlue navigationBar.setBackgroundImage(Self.solidImage(color: .demoBlue), for: .default) navigationBar.shadowImage = UIImage() navigationBar.isTranslucent = false navigationBar.titleTextAttributes = [.foregroundColor: UIColor.white] } } private static func solidImage(color: UIColor) -> UIImage { return UIGraphicsImageRenderer(size: CGSize(width: 1, height: 1)).image { context in color.setFill() context.fill(CGRect(x: 0, y: 0, width: 1, height: 1)) } } } private extension UIColor { static let demoBlue = UIColor(red: 0.0, green: 0.46, blue: 0.70, alpha: 1.0) }
Replies
2
Boosts
1
Views
292
Activity
1d
How to check for multiple scene support on iPhone Duo?
I have an iOS app that supports multiple scenes on the iPad, and which has an "Open in Another Window" feature which creates a new window scene. I would like to bring this feature to the iPhone Duo. On the iPhone Duo, of course, creating new windows is only supported when the device is open; when it is closed, creating new windows does not work. (If you try, an error is thrown.) Until now, the way I have checked whether my "Open in Another Window" feature should be available is to check to see if UIApplication.shared.supportsMultipleScenes is true. This has always returned false for previous iPhones and true for iPads. Unfortunately, however, this does not work as expected on the iPhone Duo. On the Duo, I would expect supportsMultipleScenes to return true when the device is open, but false when it is closed. This is not the case: it returns true for all poses. (Filed as #FB24948411 as this doesn't seem right to me.) So it does not help me decide whether the feature should be available. UIWindowScene.ActivationAction does work as expected when used in a menu, with the action auto-hiding when the Duo is in the closed pose. In my app, though, I need more than just an auto-hiding menu item; I need to check whether creating a new window is currently possible for certain UI availability decisions. What, then, is the correct way of checking this, if it's not with supportsMultipleScenes? Given that UIWindowScene.ActivationAction is able to hide itself, I assume there is some better way of checking that I have missed.
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
0
Boosts
0
Views
70
Activity
2d
SplitViewController removed the ability to have a side menu on iPhone
Sometime pre-iOS 26 it was possible to use a SplitViewController so that on iPhone you saw the master as a side menu (e.g. hamburger), and the detail full screen. While on iPad you would see the master displayed in a sidebar that could be closed, with the detail fullscreen. This has changed, using a SplitViewController on iPhone now forces you into having 2 fullscreen screens, with a push/pop layout and a back button. In situations where you want the detail screen to open first, this results in users opening the app to find a back button already presented, despite having not navigated anywhere. They must "return" to a screen they never saw. I really despise this layout and find it to be quite a UX issue. But given the new iPhone Duo, using the SplitViewController is now one of the easiest ways to maintain the necessary responsiveness needed, forcing us to accept this behaviour on regular iPhones. Can we PLEASE get the old functionality back, where we can explicitly state on iPhone that the master will always be displayed as a menu?
Replies
0
Boosts
0
Views
81
Activity
4d
Stale blur glass effect appears at top of UITableView and WKWebView after user updates device to iOS 27, app built with Xcode 26.3
Environment App built with Xcode 26.3 (iOS 26 SDK) Deployment Target: iOS 16+ Issue occurs only on devices upgraded to iOS 27. Works perfectly on iOS 26.x. Problem description: After end‑user upgrades their iPhone to iOS 27, a persistent stale frosted‑glass / blur rendering effect appears at the top area of screens. This symptom occurs both on native UITableView and inside WKWebView. No blur‑related code (UIVisualEffectView / backdrop‑filter) is added by our application. Layout frames, insets and contentOffset are all correct. Reproduction hints: The issue can be triggered after presenting then dismissing a WKWebView which loads H5 with overlay popup. Rendering state seems to leak to the whole app process. The leftover blur remains until push/pop the view controller. Is this an iOS 27 system bug, or do we need special adaptation for existing apps built with older Xcode 26.3 SDK? What is the proper workaround for apps compiled with Xcode26.3, since liquidGlassEffectEnabled is only available in iOS27 SDK and cannot be accessed in our current build environment.
Replies
5
Boosts
0
Views
423
Activity
4d
Custom UIPresentationController cannot match iPhone Duo sheet vertical-bar behavior
Tested on iPhone Duo with iOS 27.1 in Xcode 27.1 Beta Presented VC returns .disabled from preferredVerticalBarBehavior. With UISheetPresentationController, the sheet's trailing safe-area inset is removed at all detents (including default medium and large, plus custom detents at various fixed heights). The interesting part: the status bar remains in the vertical bar for detents below UISheetPresentationControllerDetentResolutionContext.maximumDetentValue, but at detents that are greater than or equal to that maximumDetentValue, the status bar moves to the top. With a custom UIPresentationController: Default shouldPresentInFullscreen == true: trailing inset remains, regardless of presented VC's preferredVerticalBarBehavior (possibly expected) With shouldPresentInFullscreen == false: trailing inset is removed, but the status bar moves to the top regardless of the presented view's height. Using automatic as preferredVerticalBarBehavior keeps the status bar on the right, but also keeps the safe-area insets increased. Is UISheetPresentationController applying detent-aware, presentation-scoped vertical bar behavior? Is there a public way for a custom UIPresentationController to remove the sheet's vertical-bar inset while keeping the status bar vertical [until the presentation reaches full height]?
Replies
0
Boosts
0
Views
74
Activity
5d
Tapping the top area of iPhone Duo does not respond in Device Hub
I’m simulating an iPhone Duo using Xcode 27.1 beta, and I’m having trouble tapping buttons placed near the top of the screen. It seems that the top ~20 pixels of the screen are not responding to taps. In my ViewController, preferredScreenEdgesDeferringSystemGestures returns .all, so system gestures should require two swipes to be triggered. However, a simple tap in this area does not seem to be recognized. This appears to happen only on iPhone Duo; taps work normally on other iPhone models. Does anyone know whether this behavior is expected to occur on the actual iPhone Duo hardware as well, or is it specific to the simulator? For reference, the buttons are positioned according to LayoutMarginsGuide with Safe Area. FB24914903 I wonder if anyone knows how to get the top margin size programmatically.
Replies
0
Boosts
0
Views
88
Activity
5d
Finger input interrupted while drawing with Apple Pencil + palm resting on display
I’m investigating an issue with simultaneous Apple Pencil and finger input on iPad. Apple Pencil + finger input works correctly while the Pencil user’s hand/palm is off the display. However, when drawing naturally with Apple Pencil with the palm resting on the display, an existing finger drawing contact elsewhere on the screen can be cancelled and then stop receiving input for several seconds. Pencil input continues normally throughout. Initially I suspected PencilKit, but I’ve reproduced the underlying behaviour below PencilKit/SwiftUI. Instrumenting UIKit at UIApplication.sendEvent shows the finger touch being cancelled and, in some cases, no further events for that finger for ~4–5 seconds while Pencil MOVED events continue to arrive normally. Everything delivered to the application is accounted for, so this appears to occur before our drawing/rendering code. Is this expected behaviour from the iPad’s Pencil/palm rejection? More specifically: Is there any supported way to tell UIKit that an existing finger contact should remain intentional while Pencil + palm contact is present? Is palm rejection configurable at this level? Is there another public input API we should be using for this scenario? We’re currently testing UIEvent.coalescedTouches(for:) to determine whether additional genuine finger samples are available during these apparent gaps, but haven’t completed that test yet. Any guidance on whether this interaction is expected to be supportable through public UIKit APIs would be appreciated.
Replies
1
Boosts
0
Views
311
Activity
5d
UndoManager access from Keyboard extension
Hi,I'm trying to implement undo and redo, in a Custom keyboard extension. However, calling undo() on the UndoManager from UIInputViewController, doesn't seems to work. Is there any other way of getting the UndoManager from the app the keyboard is connected to?Or do I need create my own logic to store what a user has written?
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
1
Boosts
1
Views
385
Activity
5d
Best Practice to adopt iPhone Duo
What's the best practices to adopt iPhone Duo for a production UIKit app? What few things we need to consider during the development? "As long as we use auto layout, it should be fine" is this correct term for iPhone Duo? Meaning, as long as our app use proper auto layout, our app should be able to support iPhone Duo properly.
Replies
0
Boosts
0
Views
61
Activity
5d
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
UITableView behavior on iPhone Duo
I’m adapting a UIKit app for iPhone Duo and noticed that UITableViewController separators extend underneath the navigation and tab bar controls when those controls move to the side. The cell content appears to respect the safe area, but the separators continue to the screen edge. When using a UITableView inside a regular UIViewController, constraining its horizontal edges to the parent’s safeAreaLayoutGuide prevents this. With UITableViewController, however, the table view is the controller’s root view. The attached screenshots show the difference: Screenshot 1: Separators extend underneath the side controls. Screenshot 2: Separators stop at the safe area boundary. Should UITableViewController respect these safe area boundaries out of the box, including for separators, when system controls move to the side? Or is drawing separators underneath those controls the intended behavior? If automatic adaptation is expected, could this be a UIKit issue?
Replies
0
Boosts
0
Views
95
Activity
6d
UIAlertController.addTextField results in broken text field in 27.1
I just downloaded Xcode 27.1 to test out the iPhone Duo simulator, and I notice that UIAlertController.addTextField, which was working fine in 27, is now very broken, resulting in a text field that is squashed vertically and pushed over to the right in the alert sheet. This is very easy to reproduce - the following code will show the problem if you build in Xcode 27.1 and run on iOS 27.1 or iOS 27.2: let alert = UIAlertController(title: "Create Something", message: "Enter a title.", preferredStyle: .alert) alert.addTextField { textField in textField.placeholder = "Title" } alert.addAction(UIAlertAction(title: "Cancel", style: .cancel)) present(alert, animated: true) The bug isn't limited to the Duo, but can also be seen on an iPad (and probably a regular phone). I would post a screenshot, but the last time I tried that, the forum software erroneously banned me for two weeks. I have reported this as bug #FB24889500, but given that we use alerts with text fields for users adding new items to the outline in our app, something the user does a lot, I'm wondering if there is a workaround, since this is going to make our app look very buggy.
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
0
Boosts
0
Views
76
Activity
1w
System permission alerts mis‑positioned for AppDelegate‑only legacy UIKit app on iPhone Duo (Xcode26 / iOS26 SDK)
Hi everyone, We are validating our existing legacy UIKit application on iPhone Duo, built using Xcode26 and the iOS26 SDK. Our app follows the classic AppDelegate‑only pattern. We do not adopt UIApplicationSceneManifest or SceneDelegate, so it runs under the system’s legacy compatibility container window. The codebase still heavily uses UIScreen.main, and we have not yet adopted UIWindowScene. Full scene‑based migration is planned for Xcode27, but we need to ship builds with Xcode26 for now and expect reasonable compatibility on iPhone Duo hardware. Most of our application UI displays correctly inside this system‑provided compatibility window. However we noticed a critical positioning defect for system‑owned permission alerts. System‑rendered authorization dialogs (push notification permission, photo library access, location permission — these are drawn by the system process, not our app) are positioned relative to the full physical inner display of iPhone Duo. Instead of centering within our app’s compatibility‑mode container viewport, these permission pop‑ups appear offset and misaligned against our app’s visible window bounds. I have three key questions: Is this mis‑positioning of system permission alerts expected documented behavior for non‑Scene, AppDelegate‑only legacy apps running inside compatibility mode on iPhone Duo when built with Xcode26 SDK? While we remain on Xcode26 SDK, before completing full scene‑based lifecycle migration for Xcode27: are there any known workarounds to correct or mitigate this system permission alert offset issue? Or is this a hard limitation of the legacy compatibility mode in Xcode26, meaning we cannot fix it until we fully migrate to scene‑based app lifecycle? If this is intended limitation, could anyone point me to official Apple documentation that covers this exact behavior for legacy apps on iPhone Duo? Thanks for any insight.
Replies
0
Boosts
0
Views
238
Activity
1w
UISheetPresentationController issues on iPhone Duo
I have an App where I use the UISheetPresentationController to present a menu as a "drawer" (like the "FindMy" or "Maps") App. Because the sheet is presented over a map, I made the sheet semi-transparent/blurry, so the Map shines through, which looks nice. The sheet is using a UITableView with the "insetGroup" style, so the table cells have the nice rounded borders and there are margins to the sheet borders. When running the App on the iPhone Duo (Simulator) on the outer display, the tableView does no longer respect the "insetGroup" style, it is rendered like it would have the "plain" style, which destroys everything that look good. No rounded borders, no margins. However if I opt-out of the automatic "vertical toolbar behavior" (overriding preferredVerticalBarBehavior so it returns "disabled"), then everything looks great again, however then the sheet content might overlap with the sidebar icons and camera because it now covers the whole area up to the right screen border. Is this supposed to be this way (if yes, why?), is there a way to fix this, or do we have to wait for a bugfix within iOS 27.1? The tableview still claims to have the "insetGrouped" style, just it does not render this way. I did not see any similar issues under other circumstances. Only UISheetPresentationController seems to be affected by this. Is there a way to correctly detect if the App is running on an iPhone Duo, so we could use this detection to add workarounds for such issues?
Replies
1
Boosts
0
Views
201
Activity
1w