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

How to set custom height for keyboard extension without resize flicker?
Description I'm developing a custom keyboard extension using UIInputViewController and need to set a specific height of 268 points. The keyboard functions correctly, but there's a visible flicker and resize animation during launch that I cannot eliminate. The Problem When the keyboard launches, iOS provides incorrect heights before settling on the correct one. At launch, the view starts at 0×0. Around 295ms later, iOS sets the frame to 440×956 which is full screen height and wrong. Around 373ms, iOS changes it to 440×452 which is still wrong. Finally around 390ms, iOS settles at 440×268 which matches our constraint. This causes visible flicker as the view resizes three times rapidly. The keyboard appears to shrink from full screen down to the correct height, and users can clearly see this animation happening. What I've Tried I've tried adding a height constraint on self.view which gives me the correct height but causes the visible flicker. I created a custom UIInputView subclass and overrode intrinsicContentSize to return my desired height. iOS completely ignores this and gives random heights like 471pt, 680pt, or 956pt instead. I set allowsSelfSizing to true on my UIInputView subclass. iOS ignores this property. I set preferredContentSize on the view controller. iOS ignores this as well. I tried adding the constraint in viewDidAppear instead of viewDidLoad, thinking iOS might have settled by then. It still causes flicker. I overrode the frame and bounds setters on my UIInputView to clamp the height to my desired value. iOS bypasses these overrides somehow. I overrode layoutSubviews to force the correct height after the super call. iOS still applies its own height. Specific Question What is the correct API or technique to specify a keyboard extension's height that iOS will respect immediately upon launch, without triggering the resize animation sequence? Other third-party keyboards like Grammarly and SwiftKey appear to have solved this problem. Their keyboards appear at the correct height without any visible flicker. How do they achieve this? Expected Outcome The keyboard should appear at 268pt height on the first frame with no visible resize animation. Steps to Reproduce Create a new iOS App project in Xcode and add a Keyboard Extension target. In KeyboardViewController.swift, add a height constraint in viewDidLoad: override func viewDidLoad() { super.viewDidLoad() let heightConstraint = view.heightAnchor.constraint(equalToConstant: 268) heightConstraint.priority = .defaultHigh heightConstraint.isActive = true let label = UILabel() label.text = "Demo Keyboard" label.textAlignment = .center label.translatesAutoresizingMaskIntoConstraints = false view.addSubview(label) NSLayoutConstraint.activate([ label.centerXAnchor.constraint(equalTo: view.centerXAnchor), label.centerYAnchor.constraint(equalTo: view.centerYAnchor) ]) } Build and run on a physical device. Enable the keyboard in Settings, then General, then Keyboard, then Keyboards. Open any app with a text field and switch to the custom keyboard using the globe button. Observe the height changing from around 956pt to 452pt to 268pt with visible animation. Environment iOS 17 and iOS 18 and 26.2, Xcode 16 and Xcode 26, affects all iPhone models tested, reproducible on both simulator and physical device.
2
5
757
3h
UINavigationController, Nav Bar does not extend to top on iPhone Duo
When using a background color for a UINavigation controller it seems the header does not extend to the top of the device for iPhone Duo when its closed in portrait mode. See screenshot. It should fill the entire 'status' bar up to top of device, Landscape correctly works, its just Portrait. Any thoughts on if this is 'expected' behavior? Seems odd to not just extend the navbar alll the way to the top.
Topic: UI Frameworks SubTopic: UIKit Tags:
4
1
465
11h
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) }
3
1
492
13h
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.
1
0
170
14h
Layout glitch after rotation when using UIWindowScene sizeRestrictions on iPadOS 26
Hi everyone, I am experiencing a strange rendering issue on iPadOS 26 when sizeRestrictions.minimumSize is set on a UIWindowScene. After rotating the device and then rotating it back to the original orientation, the window appears to be stretched based on its previous dimensions. This resulting "stretched" area does not resize or redraw correctly, leaving a significant black region on the screen. Interestingly, as soon as I interact with the window (e.g., a slight drag or touch), the UI snaps back to its intended state and redraws perfectly. Here is a sample code and capture of behavior. 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 } windowScene.sizeRestrictions?.minimumSize = CGSize( width: 390, height: 844 // larger than the height of iPad in landscape ) // initialize... } } Has anyone else encountered this behavior? If so, are there any known workarounds to force a layout refresh or prevent this "ghost" black area during the rotation transition? Any insights would be greatly appreciated. Thanks!
2
0
967
1d
UIImage.pngData() exports incorrect translucent colors in 16-bit PNGs
Hi there. I was responding to some user feedback reported in this PR, that suggests UIImage 16-bit PNG exports may incorrectly handle alpha premultiplication. I put together a public repro of the issue that you can find here demonstrating the issue via a playground. Here's an LLM-generated summary of the problem: On the iOS 26.5 simulator (23F77), I’m seeing UIImage.pngData() produce darker translucent colors when exporting a 16-bit image captured with UIGraphicsImageRenderer. For a pixel drawn with UIColor(white: 0.96, alpha: 0.5), the PNG stores approximately 0.48 for its RGB samples and 0.50 for alpha. This appears to retain premultiplied colors, whereas PNG requires unpremultiplied colors. Exporting the same CGImage through ImageIO’s default PNG destination produces the expected 0.96 RGB and 0.50 alpha. An 8-bit standard-range control renders correctly through both exporters. I assume this is a framework bug, but let me know if the behavior is expected for some reason. I've also filed feedback FB25109021 regarding this behavior. Thanks in advance.
0
0
64
1d
RotationCoordinator preview angle is wrong for UIRequiresFullScreen apps built with the iOS 27 SDK in Stage Manager
I'm seeing a camera preview rotation issue on iPadOS 27 that depends only on the SDK the app is linked against. I've filed it as FB25106148 and wanted to share it in case others hit the same problem. Sample project: https://github.com/bc-lee/avfoundation-rotation-coordinator-discrete-resizing-poc Setup Portrait-only iPad app with UIRequiresFullScreen = YES Front camera AVCaptureVideoPreviewLayer, rotated with AVCaptureDevice.RotationCoordinator, as in the AVCam sample: let coordinator = AVCaptureDevice.RotationCoordinator(device: device, previewLayer: previewLayer) // On every change of videoRotationAngleForHorizonLevelPreview: previewLayer.connection?.videoRotationAngle = coordinator.videoRotationAngleForHorizonLevelPreview iPad Pro 11-inch (4th generation), iPadOS 27.0.1, Stage Manager on, Rotation Lock off What happens after rotating the iPad from portrait to landscape Xcode 26.5 (iOS 26.5 SDK) Xcode 27.1 RC (iOS 27.1 SDK) App UI Stays upright for the user, letterboxed Stays in portrait and lies on its side with the device (discrete resizing, TN3192) videoRotationAngleForHorizonLevelPreview 180° 180° Camera preview Upright Sideways The source code and Info.plist are the same for both builds. interfaceOrientation, effectiveGeometry, window and screen bounds, and isInterfaceOrientationLocked are also identical between the two builds, so I couldn't find a public value that tells the two presentations apart. In the iOS 27 SDK build, applying videoRotationAngleRelative(toDeviceOrientation:) (new in iOS 27) for the scene's interface orientation, which gives 90°, instead of the horizon-level preview angle restores an upright preview. Questions Is videoRotationAngleForHorizonLevelPreview expected to reflect the discrete resizing presentation in iPadOS 27? Until that is resolved, is using videoRotationAngleRelative(toDeviceOrientation:) with the scene's interface orientation, only when linked against the iOS 27 SDK and running on iOS 27, a reasonable workaround? Has anyone else seen this, or found a better approach?
0
0
65
1d
Third-party keyboards get an extra 17pt gap at the top after switching apps on iOS 27 beta.
Feedback submitted: FB24460699 The sample projects are attached to the feedback report. Environment:iOS27 Beta6; iPhone 17Pro Problem:I have encountered a consistently reproducible third-party custom keyboard layout issue in iOS 27.0 beta 1 through beta 6. The custom keyboard initially appears correctly. If I switch apps while the text input remains focused and the keyboard remains visible, and then return to the host app, the system adds a 17-point area above the custom keyboard extension. Steps to reproduce Install and enable a third-party custom keyboard. Switch to the sample custom keyboard and open the host app so that the text editor in the center receives focus. Do not dismiss the keyboard or remove focus from the editor. Return to the Home Screen or switch to another app. Return to the host app. A new blank area now appears above the custom keyboard content. I tested both a system-determined extension view height and an extension view explicitly constrained to 180 points. Both configurations produce exactly the same change. After the foreground transition, the following extension-side values remain unchanged: view.bounds inputView.bounds extension.window.bounds view.safeAreaInsets, which remains {0, 0, 0, 0} The requested 180-point extension height Only the system keyboard frame received by the host app increases by 17 points. I also drew a rounded pink boundary inside the transparent extension root view. When the issue occurs, the new area appears outside that boundary. I tested several third-party keyboards and reproduced the issue with all of them. This suggests that the behavior is caused by iOS rather than by my app. Questions On iOS 27, is it expected behavior for a custom keyboard to gain a 17pt top area after its host app returns from the background? If this is a system issue, is there any workaround that can be used until it is fixed?
8
7
1.1k
2d
Some discussion on gestureRecognizers
I would appreciate some feedback on this simple technical point. When a gesture is defined in code, it is simply added to the view with myFirstView.addGestureRecognizer(someGesture) That's fine. But, if by mistake, the same gesture is added later to another view myOtherView.addGestureRecognizer(someGesture) myFirstView will not receive anymore the notification. That's well known and documented, because in fact the gesture references the view and can only reference one. So my point: this may be a bit misleading, as API let one believe that the gesture is attached to the view ; hence, why not attach to a second view ? wouldn't it be better to have API where view is explicitly "attached" to gesture ? someGesture.attach(to: myFirstView) Doing so, if I later someGesture.attach(to: myOtherView) it would be clearer I am changing the attached view. I noted that when we define a gesture in IB, we can only connect from the view to the gesture, not from gesture to the view which seems to follow the same logic. A simple extension does it: extension UITapGestureRecognizer { func attach(to view: UIView) { view.addGestureRecognizer(self) } } Any thought ? PS: I'm amazed by code completion. I just typed extension UITapGestureRecognizer { func attach(to view: UIView) and it completed automatically the code with view.addGestureRecognizer(self)
1
0
313
2d
Save & Edit UIBarButtonSystemItems need to be updated for the iPhone Duo
When creating a UIBarButtonItem using the standard UIBarButtonSystemItem values of UIBarButtonSystemItemSave or UIBarButtonSystemEdit you end up with text-only buttons. The text-only buttons are an issue with the iPhone Duo since such buttons do not get put in the vertical sidebar. This is a problem with a view controller with scrollable content. The text-only Save or Edit buttons can scroll out of view leaving the user confused about how to complete their work on the screen. Related is the UIViewController editButtonItem which gives the standard Edit/Done toggle button. Since the button shows the text "Edit" the button doesn't get put in the vertical sidebar. This is despite the Done display being shown as a checkmark icon.
Topic: UI Frameworks SubTopic: UIKit Tags:
0
0
54
2d
iPhone Duo - globe button appeared in RC 1 - intended change or bug?
In Xcode 27.1 RC 1 the native keyboard layout has been changed and now it shows the globe button. It looks like a bug but I'm not sure. Is the keyboard going to display the globe button in the final release? On top of that, the keyboard extension tells not to show its own globe button, so it's another point confirming that this is RC 1 regression bug. Xcode 27.1 Beta 1: Xcode 27.1 RC 1:
3
0
419
2d
UIScreen.screens.count differs on iPhone Duo sims depending on if app is IOS 26 SDK, or iOS 27 SDK
Hi there, My app uses UIScreen.screens.count (deprecated) to predict whether mirroring is happening on older iOS devices I noticed that the number of screens is different between iOS 26 SDK apps, and iOS 27 SDK apps. Can I expect that iOS 26 SDK apps will continue to return 1 screen like below for the iPhone Duo release?. I assume it's like this is to maximise compatibility. App built with SDK 26 on Xcode 27.1b1 iPhone Duo sim: UIScreen.screens.count == 1 App built with SDK 27 on Xcode 27.1b1 iPhone Duo sim: UIScreen.screens.count == 2 Thanks for the help! Sam
Topic: UI Frameworks SubTopic: UIKit Tags:
3
0
85
2d
Issue with layoutMarginsGuide under iOS 26
Before I file a bug report I wanted to verify that I'm not missing something. If I setup a view controller in a navigation controller and I add a view with a constraint that lines it up with the view controller's view's layoutMarginsGuide (leadingAnchor or trailingAnchor), in several cases the view will not line up with buttons added in the navigation bar. Under iOS 18 everything lines up as expected. To demonstrate, create a new iOS project based on Swift/Storyboard. Setup the storyboard to show a UINavigationController with one UIViewController. Then in ViewController.swift (the one embedded in the navigation controller), use the following code: import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .yellow title = "Layout Margins" let leftCancel = UIBarButtonItem(systemItem: .cancel) navigationItem.leftBarButtonItem = leftCancel let rightCancel = UIBarButtonItem(systemItem: .cancel) navigationItem.rightBarButtonItem = rightCancel let leftView = UIView() leftView.backgroundColor = .blue leftView.translatesAutoresizingMaskIntoConstraints = false self.view.addSubview(leftView) let rightView = UIView() rightView.backgroundColor = .red rightView.translatesAutoresizingMaskIntoConstraints = false self.view.addSubview(rightView) NSLayoutConstraint.activate([ leftView.widthAnchor.constraint(equalToConstant: 80), leftView.heightAnchor.constraint(equalToConstant: 80), leftView.leadingAnchor.constraint(equalTo: self.view.layoutMarginsGuide.leadingAnchor), leftView.topAnchor.constraint(equalTo: self.view.layoutMarginsGuide.topAnchor), rightView.widthAnchor.constraint(equalToConstant: 80), rightView.heightAnchor.constraint(equalToConstant: 80), rightView.trailingAnchor.constraint(equalTo: self.view.layoutMarginsGuide.trailingAnchor), rightView.topAnchor.constraint(equalTo: self.view.layoutMarginsGuide.topAnchor), ]) } } This adds a "Cancel" button to both ends of the navigation bar and it adds two little square views lined up with the leading and trailing layout margins. Here's the results: iPad running iPadOS 26 beta 3 (note the misalignment). This is really jarring when trying to align another glass button below the cancel button: iPad running iPadOS 18.5 (aligned just fine): iPhone in portrait running iOS 26 beta (aligned just fine): iPhone in landscape running iOS 26 beta (no alignment at all): iPhone in portrait running iOS 18.5 (aligned just fine): iPhone in landscape running iOS 18.5 (aligned just fine): Under iOS 26 on an iPhone (simulator at least) in portrait, the cancel buttons line up with the colored squares. That's good. In landscape, the colored squares have much larger margins as expected (due to the larger safe areas caused by the notch), but the cancel buttons in the navigation bar are not using the same margins. This one is debatable. Under iOS 18 the cancel buttons use larger margins to match the larger safe area. But I can see why under iOS 26 they changed this since the navigation bar doesn't interfere with the notch. But it's inconsistent. Under iOS 26 on an iPad (simulator at least), it's wrong in any orientation. Despite the lack of any notch or need for a larger safe area, the colored squares are indented just a bit more than the buttons in the navigation bar. I see no reason for this. Under iOS 18 everything lines up as expected. My real question at this point: Is the mismatched margins on an iPad under iOS 26 between the buttons in the navigation bar and other views added to the view controller a likely bug or am I missing something?
3
0
1.2k
2d
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?
1
0
224
3d
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?
2
1
340
3d
Dismiss/Close button - leading or trailing edge?
What is the recommended position of the "X" button dismissing a modal sheet on iOS? When we have "X" and "✓" the case is easy, but what if we just have "X" button? For example, on a "What's New" screen. I found guidelines here: https://developer.apple.com/design/human-interface-guidelines/sheets Based on resizable sheets presented there, the "X" button should be on leading edge. However, iOS is inconsistent and sometimes it presents the button on the leading edge and sometimes on the trailing edge. How do you approach it? Do you prefer having it on the leading or trailing edge? SwiftUI provides ToolbarItem(placement: .cancellationAction) , but it doesn't feel like the right placement. cancellationAction sounds like something for actionable sheets when we have something to be cancelled. I'm missing placement: .dismiss :).
1
0
1.2k
3d
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
3
1
520
4d
Can we opt out of the Horizontal Bar on the iPhone Duo?
We are aware that we can opt out of the vertical bar to make it horizontal for folded and unfolded landscape: https://developer.apple.com/documentation/uikit/uiviewcontroller/preferredverticalbarbehavior As per the title, we would like to know if if the reverse is possible (i.e. can we have the unfolded portrait display a vertical bar instead of a horizontal one)
1
0
130
4d
How to set custom height for keyboard extension without resize flicker?
Description I'm developing a custom keyboard extension using UIInputViewController and need to set a specific height of 268 points. The keyboard functions correctly, but there's a visible flicker and resize animation during launch that I cannot eliminate. The Problem When the keyboard launches, iOS provides incorrect heights before settling on the correct one. At launch, the view starts at 0×0. Around 295ms later, iOS sets the frame to 440×956 which is full screen height and wrong. Around 373ms, iOS changes it to 440×452 which is still wrong. Finally around 390ms, iOS settles at 440×268 which matches our constraint. This causes visible flicker as the view resizes three times rapidly. The keyboard appears to shrink from full screen down to the correct height, and users can clearly see this animation happening. What I've Tried I've tried adding a height constraint on self.view which gives me the correct height but causes the visible flicker. I created a custom UIInputView subclass and overrode intrinsicContentSize to return my desired height. iOS completely ignores this and gives random heights like 471pt, 680pt, or 956pt instead. I set allowsSelfSizing to true on my UIInputView subclass. iOS ignores this property. I set preferredContentSize on the view controller. iOS ignores this as well. I tried adding the constraint in viewDidAppear instead of viewDidLoad, thinking iOS might have settled by then. It still causes flicker. I overrode the frame and bounds setters on my UIInputView to clamp the height to my desired value. iOS bypasses these overrides somehow. I overrode layoutSubviews to force the correct height after the super call. iOS still applies its own height. Specific Question What is the correct API or technique to specify a keyboard extension's height that iOS will respect immediately upon launch, without triggering the resize animation sequence? Other third-party keyboards like Grammarly and SwiftKey appear to have solved this problem. Their keyboards appear at the correct height without any visible flicker. How do they achieve this? Expected Outcome The keyboard should appear at 268pt height on the first frame with no visible resize animation. Steps to Reproduce Create a new iOS App project in Xcode and add a Keyboard Extension target. In KeyboardViewController.swift, add a height constraint in viewDidLoad: override func viewDidLoad() { super.viewDidLoad() let heightConstraint = view.heightAnchor.constraint(equalToConstant: 268) heightConstraint.priority = .defaultHigh heightConstraint.isActive = true let label = UILabel() label.text = "Demo Keyboard" label.textAlignment = .center label.translatesAutoresizingMaskIntoConstraints = false view.addSubview(label) NSLayoutConstraint.activate([ label.centerXAnchor.constraint(equalTo: view.centerXAnchor), label.centerYAnchor.constraint(equalTo: view.centerYAnchor) ]) } Build and run on a physical device. Enable the keyboard in Settings, then General, then Keyboard, then Keyboards. Open any app with a text field and switch to the custom keyboard using the globe button. Observe the height changing from around 956pt to 452pt to 268pt with visible animation. Environment iOS 17 and iOS 18 and 26.2, Xcode 16 and Xcode 26, affects all iPhone models tested, reproducible on both simulator and physical device.
Replies
2
Boosts
5
Views
757
Activity
3h
UINavigationController, Nav Bar does not extend to top on iPhone Duo
When using a background color for a UINavigation controller it seems the header does not extend to the top of the device for iPhone Duo when its closed in portrait mode. See screenshot. It should fill the entire 'status' bar up to top of device, Landscape correctly works, its just Portrait. Any thoughts on if this is 'expected' behavior? Seems odd to not just extend the navbar alll the way to the top.
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
4
Boosts
1
Views
465
Activity
11h
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
3
Boosts
1
Views
492
Activity
13h
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
1
Boosts
0
Views
170
Activity
14h
Layout glitch after rotation when using UIWindowScene sizeRestrictions on iPadOS 26
Hi everyone, I am experiencing a strange rendering issue on iPadOS 26 when sizeRestrictions.minimumSize is set on a UIWindowScene. After rotating the device and then rotating it back to the original orientation, the window appears to be stretched based on its previous dimensions. This resulting "stretched" area does not resize or redraw correctly, leaving a significant black region on the screen. Interestingly, as soon as I interact with the window (e.g., a slight drag or touch), the UI snaps back to its intended state and redraws perfectly. Here is a sample code and capture of behavior. 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 } windowScene.sizeRestrictions?.minimumSize = CGSize( width: 390, height: 844 // larger than the height of iPad in landscape ) // initialize... } } Has anyone else encountered this behavior? If so, are there any known workarounds to force a layout refresh or prevent this "ghost" black area during the rotation transition? Any insights would be greatly appreciated. Thanks!
Replies
2
Boosts
0
Views
967
Activity
1d
UIImage.pngData() exports incorrect translucent colors in 16-bit PNGs
Hi there. I was responding to some user feedback reported in this PR, that suggests UIImage 16-bit PNG exports may incorrectly handle alpha premultiplication. I put together a public repro of the issue that you can find here demonstrating the issue via a playground. Here's an LLM-generated summary of the problem: On the iOS 26.5 simulator (23F77), I’m seeing UIImage.pngData() produce darker translucent colors when exporting a 16-bit image captured with UIGraphicsImageRenderer. For a pixel drawn with UIColor(white: 0.96, alpha: 0.5), the PNG stores approximately 0.48 for its RGB samples and 0.50 for alpha. This appears to retain premultiplied colors, whereas PNG requires unpremultiplied colors. Exporting the same CGImage through ImageIO’s default PNG destination produces the expected 0.96 RGB and 0.50 alpha. An 8-bit standard-range control renders correctly through both exporters. I assume this is a framework bug, but let me know if the behavior is expected for some reason. I've also filed feedback FB25109021 regarding this behavior. Thanks in advance.
Replies
0
Boosts
0
Views
64
Activity
1d
RotationCoordinator preview angle is wrong for UIRequiresFullScreen apps built with the iOS 27 SDK in Stage Manager
I'm seeing a camera preview rotation issue on iPadOS 27 that depends only on the SDK the app is linked against. I've filed it as FB25106148 and wanted to share it in case others hit the same problem. Sample project: https://github.com/bc-lee/avfoundation-rotation-coordinator-discrete-resizing-poc Setup Portrait-only iPad app with UIRequiresFullScreen = YES Front camera AVCaptureVideoPreviewLayer, rotated with AVCaptureDevice.RotationCoordinator, as in the AVCam sample: let coordinator = AVCaptureDevice.RotationCoordinator(device: device, previewLayer: previewLayer) // On every change of videoRotationAngleForHorizonLevelPreview: previewLayer.connection?.videoRotationAngle = coordinator.videoRotationAngleForHorizonLevelPreview iPad Pro 11-inch (4th generation), iPadOS 27.0.1, Stage Manager on, Rotation Lock off What happens after rotating the iPad from portrait to landscape Xcode 26.5 (iOS 26.5 SDK) Xcode 27.1 RC (iOS 27.1 SDK) App UI Stays upright for the user, letterboxed Stays in portrait and lies on its side with the device (discrete resizing, TN3192) videoRotationAngleForHorizonLevelPreview 180° 180° Camera preview Upright Sideways The source code and Info.plist are the same for both builds. interfaceOrientation, effectiveGeometry, window and screen bounds, and isInterfaceOrientationLocked are also identical between the two builds, so I couldn't find a public value that tells the two presentations apart. In the iOS 27 SDK build, applying videoRotationAngleRelative(toDeviceOrientation:) (new in iOS 27) for the scene's interface orientation, which gives 90°, instead of the horizon-level preview angle restores an upright preview. Questions Is videoRotationAngleForHorizonLevelPreview expected to reflect the discrete resizing presentation in iPadOS 27? Until that is resolved, is using videoRotationAngleRelative(toDeviceOrientation:) with the scene's interface orientation, only when linked against the iOS 27 SDK and running on iOS 27, a reasonable workaround? Has anyone else seen this, or found a better approach?
Replies
0
Boosts
0
Views
65
Activity
1d
Third-party keyboards get an extra 17pt gap at the top after switching apps on iOS 27 beta.
Feedback submitted: FB24460699 The sample projects are attached to the feedback report. Environment:iOS27 Beta6; iPhone 17Pro Problem:I have encountered a consistently reproducible third-party custom keyboard layout issue in iOS 27.0 beta 1 through beta 6. The custom keyboard initially appears correctly. If I switch apps while the text input remains focused and the keyboard remains visible, and then return to the host app, the system adds a 17-point area above the custom keyboard extension. Steps to reproduce Install and enable a third-party custom keyboard. Switch to the sample custom keyboard and open the host app so that the text editor in the center receives focus. Do not dismiss the keyboard or remove focus from the editor. Return to the Home Screen or switch to another app. Return to the host app. A new blank area now appears above the custom keyboard content. I tested both a system-determined extension view height and an extension view explicitly constrained to 180 points. Both configurations produce exactly the same change. After the foreground transition, the following extension-side values remain unchanged: view.bounds inputView.bounds extension.window.bounds view.safeAreaInsets, which remains {0, 0, 0, 0} The requested 180-point extension height Only the system keyboard frame received by the host app increases by 17 points. I also drew a rounded pink boundary inside the transparent extension root view. When the issue occurs, the new area appears outside that boundary. I tested several third-party keyboards and reproduced the issue with all of them. This suggests that the behavior is caused by iOS rather than by my app. Questions On iOS 27, is it expected behavior for a custom keyboard to gain a 17pt top area after its host app returns from the background? If this is a system issue, is there any workaround that can be used until it is fixed?
Replies
8
Boosts
7
Views
1.1k
Activity
2d
Some discussion on gestureRecognizers
I would appreciate some feedback on this simple technical point. When a gesture is defined in code, it is simply added to the view with myFirstView.addGestureRecognizer(someGesture) That's fine. But, if by mistake, the same gesture is added later to another view myOtherView.addGestureRecognizer(someGesture) myFirstView will not receive anymore the notification. That's well known and documented, because in fact the gesture references the view and can only reference one. So my point: this may be a bit misleading, as API let one believe that the gesture is attached to the view ; hence, why not attach to a second view ? wouldn't it be better to have API where view is explicitly "attached" to gesture ? someGesture.attach(to: myFirstView) Doing so, if I later someGesture.attach(to: myOtherView) it would be clearer I am changing the attached view. I noted that when we define a gesture in IB, we can only connect from the view to the gesture, not from gesture to the view which seems to follow the same logic. A simple extension does it: extension UITapGestureRecognizer { func attach(to view: UIView) { view.addGestureRecognizer(self) } } Any thought ? PS: I'm amazed by code completion. I just typed extension UITapGestureRecognizer { func attach(to view: UIView) and it completed automatically the code with view.addGestureRecognizer(self)
Replies
1
Boosts
0
Views
313
Activity
2d
Save & Edit UIBarButtonSystemItems need to be updated for the iPhone Duo
When creating a UIBarButtonItem using the standard UIBarButtonSystemItem values of UIBarButtonSystemItemSave or UIBarButtonSystemEdit you end up with text-only buttons. The text-only buttons are an issue with the iPhone Duo since such buttons do not get put in the vertical sidebar. This is a problem with a view controller with scrollable content. The text-only Save or Edit buttons can scroll out of view leaving the user confused about how to complete their work on the screen. Related is the UIViewController editButtonItem which gives the standard Edit/Done toggle button. Since the button shows the text "Edit" the button doesn't get put in the vertical sidebar. This is despite the Done display being shown as a checkmark icon.
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
0
Boosts
0
Views
54
Activity
2d
iPhone Duo - globe button appeared in RC 1 - intended change or bug?
In Xcode 27.1 RC 1 the native keyboard layout has been changed and now it shows the globe button. It looks like a bug but I'm not sure. Is the keyboard going to display the globe button in the final release? On top of that, the keyboard extension tells not to show its own globe button, so it's another point confirming that this is RC 1 regression bug. Xcode 27.1 Beta 1: Xcode 27.1 RC 1:
Replies
3
Boosts
0
Views
419
Activity
2d
UIScreen.screens.count differs on iPhone Duo sims depending on if app is IOS 26 SDK, or iOS 27 SDK
Hi there, My app uses UIScreen.screens.count (deprecated) to predict whether mirroring is happening on older iOS devices I noticed that the number of screens is different between iOS 26 SDK apps, and iOS 27 SDK apps. Can I expect that iOS 26 SDK apps will continue to return 1 screen like below for the iPhone Duo release?. I assume it's like this is to maximise compatibility. App built with SDK 26 on Xcode 27.1b1 iPhone Duo sim: UIScreen.screens.count == 1 App built with SDK 27 on Xcode 27.1b1 iPhone Duo sim: UIScreen.screens.count == 2 Thanks for the help! Sam
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
3
Boosts
0
Views
85
Activity
2d
Issue with layoutMarginsGuide under iOS 26
Before I file a bug report I wanted to verify that I'm not missing something. If I setup a view controller in a navigation controller and I add a view with a constraint that lines it up with the view controller's view's layoutMarginsGuide (leadingAnchor or trailingAnchor), in several cases the view will not line up with buttons added in the navigation bar. Under iOS 18 everything lines up as expected. To demonstrate, create a new iOS project based on Swift/Storyboard. Setup the storyboard to show a UINavigationController with one UIViewController. Then in ViewController.swift (the one embedded in the navigation controller), use the following code: import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .yellow title = "Layout Margins" let leftCancel = UIBarButtonItem(systemItem: .cancel) navigationItem.leftBarButtonItem = leftCancel let rightCancel = UIBarButtonItem(systemItem: .cancel) navigationItem.rightBarButtonItem = rightCancel let leftView = UIView() leftView.backgroundColor = .blue leftView.translatesAutoresizingMaskIntoConstraints = false self.view.addSubview(leftView) let rightView = UIView() rightView.backgroundColor = .red rightView.translatesAutoresizingMaskIntoConstraints = false self.view.addSubview(rightView) NSLayoutConstraint.activate([ leftView.widthAnchor.constraint(equalToConstant: 80), leftView.heightAnchor.constraint(equalToConstant: 80), leftView.leadingAnchor.constraint(equalTo: self.view.layoutMarginsGuide.leadingAnchor), leftView.topAnchor.constraint(equalTo: self.view.layoutMarginsGuide.topAnchor), rightView.widthAnchor.constraint(equalToConstant: 80), rightView.heightAnchor.constraint(equalToConstant: 80), rightView.trailingAnchor.constraint(equalTo: self.view.layoutMarginsGuide.trailingAnchor), rightView.topAnchor.constraint(equalTo: self.view.layoutMarginsGuide.topAnchor), ]) } } This adds a "Cancel" button to both ends of the navigation bar and it adds two little square views lined up with the leading and trailing layout margins. Here's the results: iPad running iPadOS 26 beta 3 (note the misalignment). This is really jarring when trying to align another glass button below the cancel button: iPad running iPadOS 18.5 (aligned just fine): iPhone in portrait running iOS 26 beta (aligned just fine): iPhone in landscape running iOS 26 beta (no alignment at all): iPhone in portrait running iOS 18.5 (aligned just fine): iPhone in landscape running iOS 18.5 (aligned just fine): Under iOS 26 on an iPhone (simulator at least) in portrait, the cancel buttons line up with the colored squares. That's good. In landscape, the colored squares have much larger margins as expected (due to the larger safe areas caused by the notch), but the cancel buttons in the navigation bar are not using the same margins. This one is debatable. Under iOS 18 the cancel buttons use larger margins to match the larger safe area. But I can see why under iOS 26 they changed this since the navigation bar doesn't interfere with the notch. But it's inconsistent. Under iOS 26 on an iPad (simulator at least), it's wrong in any orientation. Despite the lack of any notch or need for a larger safe area, the colored squares are indented just a bit more than the buttons in the navigation bar. I see no reason for this. Under iOS 18 everything lines up as expected. My real question at this point: Is the mismatched margins on an iPad under iOS 26 between the buttons in the navigation bar and other views added to the view controller a likely bug or am I missing something?
Replies
3
Boosts
0
Views
1.2k
Activity
2d
Ghost Padding on NavigationBarPlatterContainer
Hello, I have a SwiftUI View sitting in the UIHosting view controller. On rotation to landscape, the system would add padding to the toolbar. I presume it's the nav bar. Anyone experienced this? What would be this space? padding? content margin?
Replies
4
Boosts
0
Views
465
Activity
2d
Accent Color is broken in Xcode 27.1 RC 1
In Xcode 27.1 RC 1 there is a regression bug displaying incorrect accent color across the app. It worked correctly in Xcode 27.1 Beta 1. It affects borderPromintent top bar buttons and tab bars: https://x.com/kulik_wojciech/status/2107252543709692166?s=20 I already reported it as a bug: FB25074768
Replies
4
Boosts
0
Views
134
Activity
3d
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
1
Boosts
0
Views
224
Activity
3d
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
2
Boosts
1
Views
340
Activity
3d
Dismiss/Close button - leading or trailing edge?
What is the recommended position of the "X" button dismissing a modal sheet on iOS? When we have "X" and "✓" the case is easy, but what if we just have "X" button? For example, on a "What's New" screen. I found guidelines here: https://developer.apple.com/design/human-interface-guidelines/sheets Based on resizable sheets presented there, the "X" button should be on leading edge. However, iOS is inconsistent and sometimes it presents the button on the leading edge and sometimes on the trailing edge. How do you approach it? Do you prefer having it on the leading or trailing edge? SwiftUI provides ToolbarItem(placement: .cancellationAction) , but it doesn't feel like the right placement. cancellationAction sounds like something for actionable sheets when we have something to be cancelled. I'm missing placement: .dismiss :).
Replies
1
Boosts
0
Views
1.2k
Activity
3d
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
3
Boosts
1
Views
520
Activity
4d
Can we opt out of the Horizontal Bar on the iPhone Duo?
We are aware that we can opt out of the vertical bar to make it horizontal for folded and unfolded landscape: https://developer.apple.com/documentation/uikit/uiviewcontroller/preferredverticalbarbehavior As per the title, we would like to know if if the reverse is possible (i.e. can we have the unfolded portrait display a vertical bar instead of a horizontal one)
Replies
1
Boosts
0
Views
130
Activity
4d