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

iPhone Duo - Buggy margin shift while dragging down a modal view controller
Has anyone else run into this issue? If you present a view controller and set its isModalInPresentation property to true, then when you try to drag down the view controller (which can't be dismissed), the view controller's content on the side of the vertical toolbar is shifted inward. This happens on a closed iPhone Duo. Even the title shifts if the vertical toolbar is on the left side. To replicate, create a Swift/UIKit project. Edit the main storyboard by deleting the default view controller scene and add a navigation controller (and its default root view controller). Set the class for the root view controller to ViewController. Then replace the default ViewController.swift code with the following: import UIKit class ViewController: UITableViewController { override func viewDidLoad() { super.viewDidLoad() let modal = UIBarButtonItem(systemItem: .add, primaryAction: .init(handler: { _ in let vc = ViewController() vc.title = "Some Modal" // If the following is true, dragging the modal view controller // down results in the table margins being shifted on whichever // side has a vertical toolbar. This happens on the iPhone Duo // when closed in either portrait or landscape. Whichever side // has the vertical toolbar gets shifted. // When the iPhone Duo is open the modal appears in a form sheet // and it does not demonstrate the issue. // The navigation title is also affected when the iPhone Duo is // closed and in landscape with the vertical toolbar on the left. // If the following is false, dismissing the modal by dragging it // down does NOT result in any change in the table's margins. vc.isModalInPresentation = true // false let nc = UINavigationController(rootViewController: vc) self.present(nc, animated: true) })) navigationItem.rightBarButtonItem = modal } } extension ViewController { override func numberOfSections(in tableView: UITableView) -> Int { 2 } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 4 } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // Some simple table cells to demonstrate the margin shift let cell = tableView.dequeueReusableCell(withIdentifier: "cell") ?? UITableViewCell(style: .value1, reuseIdentifier: "cell") cell.textLabel?.text = "Some Text" cell.detailTextLabel?.text = "Value" cell.accessoryType = .disclosureIndicator return cell } } Build and run the app with Xcode 27.1 and run it on an iPhone Duo (simulated or real). Tap the + icon to display the modal view controller (just another instance of ViewController). Now try to drag down the modal view controller. Notice the margin shift if the Duo is closed. There is no margin shift is the Duo is open or if isModalInPresentation is set to false. This has been reported as FB25221160.
0
0
14
59m
How to distinguish a foreground cold launch from a background task cold launch?
I'm trying to determine why my UIKit application was launched, specifically whether it was launched by the user or by the system to execute a background task. I recently added a BGProcessingTask to update data overnight. Consider this scenario: The user backgrounds the app at 10 AM. A background task is scheduled with earliestBeginDate set to 4 AM the following day. During those 18 hours, iOS terminates the app's process to reclaim memory. iOS later decides to execute the scheduled background task and launches a new app process in the background. My understanding is that this results in a cold launch, including a call to application(_:didFinishLaunchingWithOptions:) and the initialization performed there. This matters because some of our startup initialization triggers network requests that are unnecessary when the app is launched only to perform a background task. Questions 1. Can iOS relaunch a previously terminated app to execute a scheduled BGProcessingTask? I'm referring specifically to termination by the system (for example, memory pressure), not the user force-quitting the application. 2. Is there a reliable way to distinguish a foreground cold launch from a background task cold launch inside application(_:didFinishLaunchingWithOptions:)? I tried checking UIApplication.shared.applicationState, but in my testing it was .background during didFinishLaunchingWithOptions in both scenarios, including when the user launched the app by tapping its icon. Is there another documented API or launch context that reliably identifies why the process was started? I'm aware that iOS provides launch options for certain launch scenarios, but I'm specifically interested in distinguishing a background task-triggered cold launch from a user-initiated foreground cold launch. 3. If this distinction cannot be made reliably during didFinishLaunchingWithOptions, what is the earliest lifecycle callback where I can determine that the app is entering the foreground? For example, should foreground-specific initialization be deferred until scene(_:willConnectTo:options:), sceneWillEnterForeground(_:), or another callback? I'm specifically looking for a documented and reliable lifecycle signal, rather than heuristics or arbitrary delays. The goal is to avoid unnecessary startup initialization and network requests when iOS launches the application solely to execute a background task.
2
0
90
8h
iPhone Duo: Making a custom popup avoid the hinge by presenting it as an arrowless popover
Background On iPhone Duo, when the device is unfolded and then partially folded, system alerts (UIAlertController) are automatically repositioned so they stay clear of the hinge. Apple's Tech Talk confirms this: "The system automatically repositions components around the reserved region." Our app uses a custom popup: a view controller presented with .overFullScreen that lays out its own dimming view and a custom-drawn view (here, a coupon ticket with notched edges) in the center of the screen. This popup is not repositioned. It stays centered on screen, right on top of the fold. The recommended approach for custom UI is to query view.reservedRegions(kind: .division) and lay out around the fold manually. Before going that route, I tried something simpler. What I tried The Tech Talk lists popovers among the components the system repositions. So I presented the same custom view as a popover with no arrow, anchored to the center of the presenting view: final class CouponPopoverViewController: UIViewController, UIPopoverPresentationControllerDelegate { private let ticketView = CouponTicketView() // the custom popup view init(centeredIn sourceView: UIView) { super.init(nibName: nil, bundle: nil) modalPresentationStyle = .popover guard let popover = popoverPresentationController else { return } popover.sourceView = sourceView popover.sourceRect = Self.centerPoint(of: sourceView.bounds) popover.permittedArrowDirections = [] // Drop the system popover chrome so only the custom view (and its own shadow) is visible. popover.popoverBackgroundViewClass = ClearPopoverBackgroundView.self popover.delegate = self } required init?(coder: NSCoder) { fatalError() } override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .clear ticketView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(ticketView) NSLayoutConstraint.activate([ ticketView.topAnchor.constraint(equalTo: view.topAnchor), ticketView.bottomAnchor.constraint(equalTo: view.bottomAnchor), ticketView.leadingAnchor.constraint(equalTo: view.leadingAnchor), ticketView.trailingAnchor.constraint(equalTo: view.trailingAnchor) ]) preferredContentSize = ticketView.systemLayoutSizeFitting( CGSize(width: 300, height: UIView.layoutFittingCompressedSize.height), withHorizontalFittingPriority: .required, verticalFittingPriority: .fittingSizeLevel ) } private static func centerPoint(of bounds: CGRect) -> CGRect { CGRect(x: bounds.midX, y: bounds.midY, width: 0, height: 0) } // Keep it a popover on iPhone instead of adapting to a sheet. func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle { .none } // Re-anchor to the center after rotation or fold changes. func popoverPresentationController(_ popoverPresentationController: UIPopoverPresentationController, willRepositionPopoverTo rect: UnsafeMutablePointer<CGRect>, in view: AutoreleasingUnsafeMutablePointer<UIView>) { rect.pointee = Self.centerPoint(of: view.pointee.bounds) } } /// A popover background that draws nothing: no arrow, no insets, no default appearance. final class ClearPopoverBackgroundView: UIPopoverBackgroundView { override class func arrowBase() -> CGFloat { 0 } override class func arrowHeight() -> CGFloat { 0 } override class func contentViewInsets() -> UIEdgeInsets { .zero } override class var wantsDefaultContentAppearance: Bool { false } override var arrowOffset: CGFloat { get { 0 } set {} } override var arrowDirection: UIPopoverArrowDirection { get { .any } set {} } } Result Partially folded, portrait (hinge runs horizontally across the middle of the screen): Before: the custom popup (.overFullScreen) stays centered, right across the hinge. After: the same view presented as an arrowless popover moves into the top half, clear of the hinge. Partially folded, book pose (vertical hinge): the popover moves to the leading page, clear of the hinge. This matches where a system UIAlertController goes in the same pose. I also checked that the popover shows correctly on the outer display (closed) and on a non-Duo iPhone (iPhone 18 Pro, iOS 27.0). Tested on: iPhone Duo simulator (iOS 27.1), Xcode 27.1 RC (27A9275) iPhone 18 Pro simulator (iOS 27.0) Things to handle when switching to a popover Tap-outside dismissal: Popovers dismiss on outside taps by default. Set isModalInPresentation = true or return false from presentationControllerShouldDismiss(_:) if the popup should only close via its buttons. Dimming: Popovers don't dim the background like a typical custom popup (compare the before and after screenshots). Add your own dimming view if needed. Chrome: By default, the system draws its own background behind the content. For a custom-shaped view, this shows through any transparent areas and clips the view's shadow. A UIPopoverBackgroundView subclass that draws nothing (above) removes it. Sizing: Set preferredContentSize explicitly. Recompute it for dynamic content and Dynamic Type. Questions This works well in my testing, but I couldn't find any documentation saying that an arrowless popover anchored to the center gets the same hinge avoidance as alerts. Is this supported behavior that we can rely on going forward? Or is reservedRegions(kind:options:) with manual layout the only recommended approach for custom popups? It would also be great to have a public API that lets custom presentations opt into the same hinge-avoidance placement that system alerts use. Hope this helps anyone else dealing with custom popups on iPhone Duo.
Topic: UI Frameworks SubTopic: UIKit Tags:
2
0
95
1d
iPhone Duo - Current SDK State
We are just 9 days before the iPhone Duo release, and the SDK is still in a pretty bad state, at least for the Keyboard Extension: Hinge detection doesn't work Reserved area detection doesn't work needsInputModeSwitchKey returns false even though iOS doesn't display its own globe button Switching between closed and fully open state loses text field focus and the keyboard disappears (regression bug - it worked in Beta 1) It's unacceptable that, with such a short release date, we still don't have a stable SDK... I expect the iPhone Duo release to be one of the buggiest releases Apple has ever done.
7
0
443
1d
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?
4
1
532
1d
How to get UISheetPresentationController width to adjust for vertical toolbar on iPhone Duo?
If you run Safari in the iPhone Duo simulator and choose to share something you get a screen similar to the following: In my own app, if I present a UIActivityViewController I get a similar result. Note that the share sheet does not cover the vertical toolbar at all. So my question is how to present a UISheetPresentationController to look the same way. In other words, how to get the width of the UISheetPresentationController to take into account the vertical toolbar? All of my existing code to create and present a UISheetPresentationController result in the UISheetPresentationController taking the full width of the screen. The contents of the sheet take the safe area into account, but that's not the same result. I need the sheet itself to be narrower. I don't see an API for this. Or does this require more complicated presentation controller / delegate setup? Here is some relevant code in the view controller that I want displayed in the sheet: self.modalPresentationStyle = .popover self.presentationController?.delegate = self if let sheet = popoverPresentationController?.adaptiveSheetPresentationController { popoverPresentationController?.passthroughViews = [] sheet.detents = [ .medium(), .large() ] sheet.largestUndimmedDetentIdentifier = nil sheet.prefersGrabberVisible = false sheet.prefersScrollingExpandsWhenScrolledToEdge = true sheet.prefersEdgeAttachedInCompactHeight = true sheet.widthFollowsPreferredContentSizeWhenEdgeAttached = true } Or maybe UISheetPresentationController is the wrong approach.
Topic: UI Frameworks SubTopic: UIKit Tags:
0
0
75
1d
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:
1
2
295
2d
UIDesignRequiresCompatibility for Xcode27
Hallo everyone, We are building our app with Xcode 27 and noticed that UIDesignRequiresCompatibility still appears to be honored on iOS 26 devices. Questions: Could you confirm whether this key is still supported on iOS 26 when built with Xcode 27? If our deployment target includes iOS 26, should we keep the key for backward compatibility, or is Apple's recommendation to remove it entirely? Additionally, are there any risks associated with removing it for iOS 26 users?
0
0
86
2d
How to preserve collection view scroll anchor when folding/unfolding iPhone Duo
The following question was asked in the Oct 13 iPhone Duo group lab: when you unfold iPhone Duo after you’ve scrolled down, does UIKit keep the position or should we re-anchor ourselves? The answer was various scroll views like collection views and text views will handle this for you to keep visible items visible, which also works when resizing the window on iPad. This is not working for me with a simple UICollectionView. What do I need to do to obtain this behavior? class ViewController: UIViewController, UICollectionViewDataSource { override func viewDidLoad() { super.viewDidLoad() let layout = UICollectionViewFlowLayout() layout.itemSize = CGSize(width: 80, height: 80) layout.minimumInteritemSpacing = 8 layout.minimumLineSpacing = 8 layout.sectionInsetReference = .fromLayoutMargins let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout) collectionView.translatesAutoresizingMaskIntoConstraints = false collectionView.backgroundColor = .systemBackground collectionView.dataSource = self collectionView.insetsLayoutMarginsFromSafeArea = true collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell") view.addSubview(collectionView) NSLayoutConstraint.activate([ collectionView.topAnchor.constraint(equalTo: view.topAnchor), collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor), collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor), collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor) ]) } func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 5000 } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) var content = UIListContentConfiguration.cell() content.text = String(indexPath.item) content.textProperties.alignment = .center cell.contentConfiguration = content var background = UIBackgroundConfiguration.clear() background.backgroundColor = .secondarySystemBackground cell.backgroundConfiguration = background return cell } } Run the app on iPhone Duo Scroll down to cell 100 on the outer display Unfold the device Expected: It should stay scrolled to item 100 Actual: It scrolled down to item 225 (or more accurately, the content offset did not change, more content was added higher up with the contentSize shrinking due to the expanded width) In the past I've put so much work into trying to maintain the expected scroll position for orientation changes on iPhone and iPad/Mac Catalyst resize events, it's surprisingly incredibly hard to get working in every scenario, so I am SUPER interested to learn the system can do it for us!
0
0
94
2d
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.
4
6
1.1k
2d
UISearchBar’s delegate method searchBarCancelButtonClicked is not called on search cancel when search bar is integrated into the navigation bar on iOS 27
Hi, I would like to share an issue with UISearchBar's delegate method searchBarCancelButtonClicked on iOS 27 beta. On iOS 27 beta, when search bar is integrated into navigation bar’s items, tapping search cancel button doesn’t invoke UISearchBar’s delegate method searchBarCancelButtonClicked:. Steps to reproduce: Create UINavigationController with one UIViewController Set up searchController. Set searchController.searchBar.delegate, preferredSearchBarPlacement = .integratedButton, searchBarPlacementAllowsToolbarIntegration = false Tap the search button and type a query Tap the search cancel button Expected: On iOS 26, the searchBarCancelButtonClicked delegate method is called. Actual: On iOS 27 beta, the searchBarCancelButtonClicked delegate method is NOT called. On iOS 27 beta, if search bar is “stacked” or placed in the toolbar rather than the navigation bar, the bug does not reproduce. I’m using Xcode Version 27.0 beta 6 with latest available iOS 27 iPhone 17 Pro simulator (24A5423a). I reported the issue via Feedback Assistant with a minimal reproduction example and 2 videos comparing the behavior between iOS 26 and iOS 27 beta. Here is the report ID: FB24636315. Here is the minimal reproduction example: // SceneDelegate.swift import UIKit class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = scene as? UIWindowScene else { return } let window = UIWindow(windowScene: windowScene) window.rootViewController = UINavigationController(rootViewController: ViewController()) window.makeKeyAndVisible() self.window = window } } // ViewController.swift import UIKit final class ViewController: UITableViewController { private let allItems = (1...30).map { "Item \($0)" } private var items: [String] = [] private var cancelCount = 0 override func viewDidLoad() { super.viewDidLoad() items = allItems updateTitle() let searchController = UISearchController(searchResultsController: nil) searchController.searchBar.delegate = self navigationItem.searchController = searchController navigationItem.preferredSearchBarPlacement = .integratedButton navigationItem.searchBarPlacementAllowsToolbarIntegration = false tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell") } private func updateTitle() { title = "Cancel presses: \(cancelCount)" } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { items.count } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) cell.contentConfiguration = { var config = cell.defaultContentConfiguration() config.text = items[indexPath.row] return config }() return cell } } extension ViewController: UISearchBarDelegate { func searchBarCancelButtonClicked(_ searchBar: UISearchBar) { print("searchBarCancelButtonClicked(_:)") cancelCount += 1 updateTitle() items = allItems tableView.reloadData() } } Thank you in advance!
Topic: UI Frameworks SubTopic: UIKit Tags:
2
2
371
2d
iOS App QuickType Bar Credit Card Autofill Not Working
According to this autofill credit card documentation we should be able to autofill credit card fields using the QuickType Bar for credit card fields, but it does not work. The QuickType Bar does not display for credit card fields (see screenshots) I have tested this on a physical device running iOS 27 (iPhone 16e), have added a card to the Autofill setting in the Wallet app, and have made sure my text fields have the correct textContentType values. I am able to autofill using the backup autofill menu, but it is less than ideal. It takes a minimum of 5 taps to autofill one field. It would be far less painful to just pull out the credit card and manually enter the information (see screenshot). Here is a link to my test project demonstrating the issue: https://drive.google.com/file/d/1wMGOUNhVnmt3rBAD0TSMf9NV39-JS9ij/view?usp=sharing
1
0
292
3d
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:
1
0
381
4d
Best practice Replacement for Edit Button on iPhone Duo
On the iPhone Duo the standard "Edit" button for navigation bars is a text-based button, and text-based buttons are not pushed to the vertical toolbars on the Duo. This looks sometimes silly, if it is the only remaining button that can not be placed in the vertical toolbar and which has the result that an almost empty horizontal navigation bar must be kept visible as well. So I guess it would be good idea to have an icon-based replacement for the Editor button to avoid having two toolbars on the Duo. Is there a best practice for the icon to pick for such an edit button? Would be "square.and.pencil" (SF Symbols) a good choice? Or better the "pencil .circle", because the "square" one is often used for text-based input? Anything better?
4
0
975
4d
UITableView row reordering no longer works under macOS 27 with Mac Catalyst
Under macOS 27 using Mac Catalyst for a UIKit-based app, If you present a view controller with a table view as a form sheet or page sheet, row reordering fails to function. You can drag a row as expected but the blue movement bar never appears and if you drop the row it simply returns to its original location. The exact same view controller presented as a popover works just fine. The exact same view controller not presented as a modal (such as the app's root controller) works just fine. This is a serious bug affecting existing applications and being reported by paying customers. This has been reported as FB25038883 which includes a simple sample app demonstrating the issue.
0
0
292
4d
UINavigationController, Nav Bar buttons incorrect layout on iPhone Duo
When presenting a UINavigationController presented via UIViewControllerRepresentable in a sheet, the top nav bar buttons aren't correctly moving to the side bar on the front screen of the Duo. They do re-orient vertically, but they do so next to the side bar and not within it. What am I doing wrong? This is how I am setting the buttons: let trimButton = UIBarButtonItem(image: UIImage(systemName: "selection.pin.in.out"), style: .plain, target: self, action: #selector(enterTrimming(_:))) navigationItem.leftBarButtonItem = trimButton navigationItem.rightBarButtonItem = cancelButton navigationItem.leftBarButtonItem?.isEnabled = true navigationItem.rightBarButtonItem?.isEnabled = true
Topic: UI Frameworks SubTopic: UIKit Tags:
1
0
108
4d
How to automatically size a table's footer view
Hi, I would like to automatically vertically size the table's footer view so that it has a fixed pre-defined minimum height and maximum height that fills up the gap between the last cell and the bottom of the safe area. How can I do this? PS: It seems to be that the footer view's size is not included in the table view's content size, correct? Regards, Hardy
Topic: UI Frameworks SubTopic: UIKit Tags:
1
0
65
4d
iPhone Duo: navigation bar item briefly moves to vertical bar during fullScreen dismissal despite .disabled
On the folded iPhone Duo display, a navigation bar item briefly moves into the vertical bar during dismissal of a full-screen modal, then jumps back to the top. Both navigation controllers consistently return .disabled from preferredVerticalBarBehavior, with childForPreferredVerticalBarBehavior returning nil. Environment Xcode 27.1 RC (27A9275), iOS 27.1 SDK, iPhone Duo simulator, folded outer display in portrait. Steps to reproduce Run the single-file UIKit example below in a scene-based app with a generated launch screen and no main storyboard. Tap the gear button on the Home screen to present Settings using .fullScreen. Tap the close button on Settings. Watch the Home screen's gear button during the dismissal animation. Expected The gear button stays in the top horizontal navigation bar throughout the transition, because the vertical bar preference is .disabled on both navigation controllers. Actual For part of the dismissal, the gear button appears below the status icons in the right-hand vertical bar region. It then jumps back to the top horizontal bar. The underlying tab bar also temporarily moves from the bottom to the right before returning. This reproduces with an otherwise empty view, standard UIKit containers, and the default bar appearance. No app code changes safeAreaInsets, bar frames, or animation timing. During the presentation/dismissal cycle, the Home view's logged right safe-area inset changes from 0 to 88 points and back to 0. In our app, content constrained to the safe area visibly narrows during the same transient change. In separate comparisons, returning .disabled from the root tab controller and content controllers, or requesting setNeedsUpdateOfVerticalBarConfiguration in appearance callbacks, did not eliminate the issue. Changing the modal to .overFullScreen avoided it in the tested simulator, but changes the underlying view controller lifecycle. The example below intentionally keeps .fullScreen to reproduce the problem. Is this expected behavior, or a known UIKit issue? Is there a supported way to keep .disabled effective throughout a fullScreen presentation/dismissal? Has this been addressed in a newer SDK/runtime? I have not tested iOS 27.2 or a physical Duo device. Minimal reproduction (one Swift file): import UIKit @main final class DemoAppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, configurationForConnecting session: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { let configuration = UISceneConfiguration(name: "Demo", sessionRole: session.role) configuration.delegateClass = DemoSceneDelegate.self return configuration } } final class DemoSceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options: UIScene.ConnectionOptions) { guard let scene = scene as? UIWindowScene else { return } let home = DemoController() home.title = "首页" let navigation = DemoNavigationController(rootViewController: home) navigation.tabBarItem = UITabBarItem(title: "首页", image: UIImage(systemName: "house"), selectedImage: nil) let tabs = UITabBarController() if #available(iOS 18.0, *) { tabs.mode = .tabBar } tabs.viewControllers = [navigation] let window = UIWindow(windowScene: scene) window.rootViewController = tabs self.window = window window.makeKeyAndVisible() } } final class DemoNavigationController: UINavigationController { // 与音剪一致:导航容器固定横向栏,不转发给子页面。 @available(iOS 27.1, *) override var preferredVerticalBarBehavior: UIVerticalBarBehavior { .disabled } @available(iOS 27.1, *) override var childForPreferredVerticalBarBehavior: UIViewController? { nil } } final class DemoController: UIViewController { override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .systemBackground if title == "设置" { navigationItem.leftBarButtonItem = UIBarButtonItem(systemItem: .close, primaryAction: UIAction { [weak self] _ in self?.dismiss(animated: true) }) } else { navigationItem.rightBarButtonItem = UIBarButtonItem( image: UIImage(systemName: "gearshape"), primaryAction: UIAction { [weak self] _ in let settings = DemoController() settings.title = "设置" let navigation = DemoNavigationController(rootViewController: settings) navigation.modalPresentationStyle = .fullScreen self?.present(navigation, animated: true) }) } } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() print("[DuoDemo] \(title ?? "") safe=\(view.safeAreaInsets) nav=\(navigationController?.navigationBar.frame ?? .zero) tab=\(tabBarController?.tabBar.frame ?? .zero)") } }
0
0
204
4d
Supported way to return the user to the app they chose after a pause screen (App Intent from an "App is Opened" automation)
We're building a Screen Time / mindful-pause app for iOS 26–27. The user adds a Shortcuts personal automation "When is Opened" that runs our App Intent. The intent passes the trigger app's Bundle Identifier (from the trigger output) and shows a short pause screen. When the user taps "Continue", we want to take them back into that app — only the one app they chose, only after they tap. Is there a supported API to open another installed app when the user taps Continue, given its bundle identifier from the Shortcuts trigger? A DTS reply in 2024 said there was no supported way (thread 740707). Has anything changed in iOS 26/27? (Related feedback: FB15500695.) If not, is it acceptable to open the chosen app via a URL scheme it registers in its Info.plist, including a third-party sign-in callback scheme, purely to bring it to the foreground? Many apps register no URL scheme. Is there a recommended pattern — e.g. handing control back to Shortcuts so the automation or the "Open App" action opens the trigger app — without the "App is Opened" automation firing again in a loop? What's the recommended way to avoid that re-fire? We currently ignore it for a short time window. A minimal sample project reproduces this (App Intent, pause screen, Continue using UIApplication.open). Happy to share it. Xcode 27.0 (27A266a), iOS 27.0 (24A446).
0
0
50
4d
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:
4
0
298
4d
iPhone Duo - Buggy margin shift while dragging down a modal view controller
Has anyone else run into this issue? If you present a view controller and set its isModalInPresentation property to true, then when you try to drag down the view controller (which can't be dismissed), the view controller's content on the side of the vertical toolbar is shifted inward. This happens on a closed iPhone Duo. Even the title shifts if the vertical toolbar is on the left side. To replicate, create a Swift/UIKit project. Edit the main storyboard by deleting the default view controller scene and add a navigation controller (and its default root view controller). Set the class for the root view controller to ViewController. Then replace the default ViewController.swift code with the following: import UIKit class ViewController: UITableViewController { override func viewDidLoad() { super.viewDidLoad() let modal = UIBarButtonItem(systemItem: .add, primaryAction: .init(handler: { _ in let vc = ViewController() vc.title = "Some Modal" // If the following is true, dragging the modal view controller // down results in the table margins being shifted on whichever // side has a vertical toolbar. This happens on the iPhone Duo // when closed in either portrait or landscape. Whichever side // has the vertical toolbar gets shifted. // When the iPhone Duo is open the modal appears in a form sheet // and it does not demonstrate the issue. // The navigation title is also affected when the iPhone Duo is // closed and in landscape with the vertical toolbar on the left. // If the following is false, dismissing the modal by dragging it // down does NOT result in any change in the table's margins. vc.isModalInPresentation = true // false let nc = UINavigationController(rootViewController: vc) self.present(nc, animated: true) })) navigationItem.rightBarButtonItem = modal } } extension ViewController { override func numberOfSections(in tableView: UITableView) -> Int { 2 } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 4 } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // Some simple table cells to demonstrate the margin shift let cell = tableView.dequeueReusableCell(withIdentifier: "cell") ?? UITableViewCell(style: .value1, reuseIdentifier: "cell") cell.textLabel?.text = "Some Text" cell.detailTextLabel?.text = "Value" cell.accessoryType = .disclosureIndicator return cell } } Build and run the app with Xcode 27.1 and run it on an iPhone Duo (simulated or real). Tap the + icon to display the modal view controller (just another instance of ViewController). Now try to drag down the modal view controller. Notice the margin shift if the Duo is closed. There is no margin shift is the Duo is open or if isModalInPresentation is set to false. This has been reported as FB25221160.
Replies
0
Boosts
0
Views
14
Activity
59m
How to distinguish a foreground cold launch from a background task cold launch?
I'm trying to determine why my UIKit application was launched, specifically whether it was launched by the user or by the system to execute a background task. I recently added a BGProcessingTask to update data overnight. Consider this scenario: The user backgrounds the app at 10 AM. A background task is scheduled with earliestBeginDate set to 4 AM the following day. During those 18 hours, iOS terminates the app's process to reclaim memory. iOS later decides to execute the scheduled background task and launches a new app process in the background. My understanding is that this results in a cold launch, including a call to application(_:didFinishLaunchingWithOptions:) and the initialization performed there. This matters because some of our startup initialization triggers network requests that are unnecessary when the app is launched only to perform a background task. Questions 1. Can iOS relaunch a previously terminated app to execute a scheduled BGProcessingTask? I'm referring specifically to termination by the system (for example, memory pressure), not the user force-quitting the application. 2. Is there a reliable way to distinguish a foreground cold launch from a background task cold launch inside application(_:didFinishLaunchingWithOptions:)? I tried checking UIApplication.shared.applicationState, but in my testing it was .background during didFinishLaunchingWithOptions in both scenarios, including when the user launched the app by tapping its icon. Is there another documented API or launch context that reliably identifies why the process was started? I'm aware that iOS provides launch options for certain launch scenarios, but I'm specifically interested in distinguishing a background task-triggered cold launch from a user-initiated foreground cold launch. 3. If this distinction cannot be made reliably during didFinishLaunchingWithOptions, what is the earliest lifecycle callback where I can determine that the app is entering the foreground? For example, should foreground-specific initialization be deferred until scene(_:willConnectTo:options:), sceneWillEnterForeground(_:), or another callback? I'm specifically looking for a documented and reliable lifecycle signal, rather than heuristics or arbitrary delays. The goal is to avoid unnecessary startup initialization and network requests when iOS launches the application solely to execute a background task.
Replies
2
Boosts
0
Views
90
Activity
8h
iPhone Duo: Making a custom popup avoid the hinge by presenting it as an arrowless popover
Background On iPhone Duo, when the device is unfolded and then partially folded, system alerts (UIAlertController) are automatically repositioned so they stay clear of the hinge. Apple's Tech Talk confirms this: "The system automatically repositions components around the reserved region." Our app uses a custom popup: a view controller presented with .overFullScreen that lays out its own dimming view and a custom-drawn view (here, a coupon ticket with notched edges) in the center of the screen. This popup is not repositioned. It stays centered on screen, right on top of the fold. The recommended approach for custom UI is to query view.reservedRegions(kind: .division) and lay out around the fold manually. Before going that route, I tried something simpler. What I tried The Tech Talk lists popovers among the components the system repositions. So I presented the same custom view as a popover with no arrow, anchored to the center of the presenting view: final class CouponPopoverViewController: UIViewController, UIPopoverPresentationControllerDelegate { private let ticketView = CouponTicketView() // the custom popup view init(centeredIn sourceView: UIView) { super.init(nibName: nil, bundle: nil) modalPresentationStyle = .popover guard let popover = popoverPresentationController else { return } popover.sourceView = sourceView popover.sourceRect = Self.centerPoint(of: sourceView.bounds) popover.permittedArrowDirections = [] // Drop the system popover chrome so only the custom view (and its own shadow) is visible. popover.popoverBackgroundViewClass = ClearPopoverBackgroundView.self popover.delegate = self } required init?(coder: NSCoder) { fatalError() } override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .clear ticketView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(ticketView) NSLayoutConstraint.activate([ ticketView.topAnchor.constraint(equalTo: view.topAnchor), ticketView.bottomAnchor.constraint(equalTo: view.bottomAnchor), ticketView.leadingAnchor.constraint(equalTo: view.leadingAnchor), ticketView.trailingAnchor.constraint(equalTo: view.trailingAnchor) ]) preferredContentSize = ticketView.systemLayoutSizeFitting( CGSize(width: 300, height: UIView.layoutFittingCompressedSize.height), withHorizontalFittingPriority: .required, verticalFittingPriority: .fittingSizeLevel ) } private static func centerPoint(of bounds: CGRect) -> CGRect { CGRect(x: bounds.midX, y: bounds.midY, width: 0, height: 0) } // Keep it a popover on iPhone instead of adapting to a sheet. func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle { .none } // Re-anchor to the center after rotation or fold changes. func popoverPresentationController(_ popoverPresentationController: UIPopoverPresentationController, willRepositionPopoverTo rect: UnsafeMutablePointer<CGRect>, in view: AutoreleasingUnsafeMutablePointer<UIView>) { rect.pointee = Self.centerPoint(of: view.pointee.bounds) } } /// A popover background that draws nothing: no arrow, no insets, no default appearance. final class ClearPopoverBackgroundView: UIPopoverBackgroundView { override class func arrowBase() -> CGFloat { 0 } override class func arrowHeight() -> CGFloat { 0 } override class func contentViewInsets() -> UIEdgeInsets { .zero } override class var wantsDefaultContentAppearance: Bool { false } override var arrowOffset: CGFloat { get { 0 } set {} } override var arrowDirection: UIPopoverArrowDirection { get { .any } set {} } } Result Partially folded, portrait (hinge runs horizontally across the middle of the screen): Before: the custom popup (.overFullScreen) stays centered, right across the hinge. After: the same view presented as an arrowless popover moves into the top half, clear of the hinge. Partially folded, book pose (vertical hinge): the popover moves to the leading page, clear of the hinge. This matches where a system UIAlertController goes in the same pose. I also checked that the popover shows correctly on the outer display (closed) and on a non-Duo iPhone (iPhone 18 Pro, iOS 27.0). Tested on: iPhone Duo simulator (iOS 27.1), Xcode 27.1 RC (27A9275) iPhone 18 Pro simulator (iOS 27.0) Things to handle when switching to a popover Tap-outside dismissal: Popovers dismiss on outside taps by default. Set isModalInPresentation = true or return false from presentationControllerShouldDismiss(_:) if the popup should only close via its buttons. Dimming: Popovers don't dim the background like a typical custom popup (compare the before and after screenshots). Add your own dimming view if needed. Chrome: By default, the system draws its own background behind the content. For a custom-shaped view, this shows through any transparent areas and clips the view's shadow. A UIPopoverBackgroundView subclass that draws nothing (above) removes it. Sizing: Set preferredContentSize explicitly. Recompute it for dynamic content and Dynamic Type. Questions This works well in my testing, but I couldn't find any documentation saying that an arrowless popover anchored to the center gets the same hinge avoidance as alerts. Is this supported behavior that we can rely on going forward? Or is reservedRegions(kind:options:) with manual layout the only recommended approach for custom popups? It would also be great to have a public API that lets custom presentations opt into the same hinge-avoidance placement that system alerts use. Hope this helps anyone else dealing with custom popups on iPhone Duo.
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
2
Boosts
0
Views
95
Activity
1d
iPhone Duo - Current SDK State
We are just 9 days before the iPhone Duo release, and the SDK is still in a pretty bad state, at least for the Keyboard Extension: Hinge detection doesn't work Reserved area detection doesn't work needsInputModeSwitchKey returns false even though iOS doesn't display its own globe button Switching between closed and fully open state loses text field focus and the keyboard disappears (regression bug - it worked in Beta 1) It's unacceptable that, with such a short release date, we still don't have a stable SDK... I expect the iPhone Duo release to be one of the buggiest releases Apple has ever done.
Replies
7
Boosts
0
Views
443
Activity
1d
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
4
Boosts
1
Views
532
Activity
1d
How to get UISheetPresentationController width to adjust for vertical toolbar on iPhone Duo?
If you run Safari in the iPhone Duo simulator and choose to share something you get a screen similar to the following: In my own app, if I present a UIActivityViewController I get a similar result. Note that the share sheet does not cover the vertical toolbar at all. So my question is how to present a UISheetPresentationController to look the same way. In other words, how to get the width of the UISheetPresentationController to take into account the vertical toolbar? All of my existing code to create and present a UISheetPresentationController result in the UISheetPresentationController taking the full width of the screen. The contents of the sheet take the safe area into account, but that's not the same result. I need the sheet itself to be narrower. I don't see an API for this. Or does this require more complicated presentation controller / delegate setup? Here is some relevant code in the view controller that I want displayed in the sheet: self.modalPresentationStyle = .popover self.presentationController?.delegate = self if let sheet = popoverPresentationController?.adaptiveSheetPresentationController { popoverPresentationController?.passthroughViews = [] sheet.detents = [ .medium(), .large() ] sheet.largestUndimmedDetentIdentifier = nil sheet.prefersGrabberVisible = false sheet.prefersScrollingExpandsWhenScrolledToEdge = true sheet.prefersEdgeAttachedInCompactHeight = true sheet.widthFollowsPreferredContentSizeWhenEdgeAttached = true } Or maybe UISheetPresentationController is the wrong approach.
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
0
Boosts
0
Views
75
Activity
1d
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
1
Boosts
2
Views
295
Activity
2d
UIDesignRequiresCompatibility for Xcode27
Hallo everyone, We are building our app with Xcode 27 and noticed that UIDesignRequiresCompatibility still appears to be honored on iOS 26 devices. Questions: Could you confirm whether this key is still supported on iOS 26 when built with Xcode 27? If our deployment target includes iOS 26, should we keep the key for backward compatibility, or is Apple's recommendation to remove it entirely? Additionally, are there any risks associated with removing it for iOS 26 users?
Replies
0
Boosts
0
Views
86
Activity
2d
How to preserve collection view scroll anchor when folding/unfolding iPhone Duo
The following question was asked in the Oct 13 iPhone Duo group lab: when you unfold iPhone Duo after you’ve scrolled down, does UIKit keep the position or should we re-anchor ourselves? The answer was various scroll views like collection views and text views will handle this for you to keep visible items visible, which also works when resizing the window on iPad. This is not working for me with a simple UICollectionView. What do I need to do to obtain this behavior? class ViewController: UIViewController, UICollectionViewDataSource { override func viewDidLoad() { super.viewDidLoad() let layout = UICollectionViewFlowLayout() layout.itemSize = CGSize(width: 80, height: 80) layout.minimumInteritemSpacing = 8 layout.minimumLineSpacing = 8 layout.sectionInsetReference = .fromLayoutMargins let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout) collectionView.translatesAutoresizingMaskIntoConstraints = false collectionView.backgroundColor = .systemBackground collectionView.dataSource = self collectionView.insetsLayoutMarginsFromSafeArea = true collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell") view.addSubview(collectionView) NSLayoutConstraint.activate([ collectionView.topAnchor.constraint(equalTo: view.topAnchor), collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor), collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor), collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor) ]) } func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 5000 } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) var content = UIListContentConfiguration.cell() content.text = String(indexPath.item) content.textProperties.alignment = .center cell.contentConfiguration = content var background = UIBackgroundConfiguration.clear() background.backgroundColor = .secondarySystemBackground cell.backgroundConfiguration = background return cell } } Run the app on iPhone Duo Scroll down to cell 100 on the outer display Unfold the device Expected: It should stay scrolled to item 100 Actual: It scrolled down to item 225 (or more accurately, the content offset did not change, more content was added higher up with the contentSize shrinking due to the expanded width) In the past I've put so much work into trying to maintain the expected scroll position for orientation changes on iPhone and iPad/Mac Catalyst resize events, it's surprisingly incredibly hard to get working in every scenario, so I am SUPER interested to learn the system can do it for us!
Replies
0
Boosts
0
Views
94
Activity
2d
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
4
Boosts
6
Views
1.1k
Activity
2d
UISearchBar’s delegate method searchBarCancelButtonClicked is not called on search cancel when search bar is integrated into the navigation bar on iOS 27
Hi, I would like to share an issue with UISearchBar's delegate method searchBarCancelButtonClicked on iOS 27 beta. On iOS 27 beta, when search bar is integrated into navigation bar’s items, tapping search cancel button doesn’t invoke UISearchBar’s delegate method searchBarCancelButtonClicked:. Steps to reproduce: Create UINavigationController with one UIViewController Set up searchController. Set searchController.searchBar.delegate, preferredSearchBarPlacement = .integratedButton, searchBarPlacementAllowsToolbarIntegration = false Tap the search button and type a query Tap the search cancel button Expected: On iOS 26, the searchBarCancelButtonClicked delegate method is called. Actual: On iOS 27 beta, the searchBarCancelButtonClicked delegate method is NOT called. On iOS 27 beta, if search bar is “stacked” or placed in the toolbar rather than the navigation bar, the bug does not reproduce. I’m using Xcode Version 27.0 beta 6 with latest available iOS 27 iPhone 17 Pro simulator (24A5423a). I reported the issue via Feedback Assistant with a minimal reproduction example and 2 videos comparing the behavior between iOS 26 and iOS 27 beta. Here is the report ID: FB24636315. Here is the minimal reproduction example: // SceneDelegate.swift import UIKit class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = scene as? UIWindowScene else { return } let window = UIWindow(windowScene: windowScene) window.rootViewController = UINavigationController(rootViewController: ViewController()) window.makeKeyAndVisible() self.window = window } } // ViewController.swift import UIKit final class ViewController: UITableViewController { private let allItems = (1...30).map { "Item \($0)" } private var items: [String] = [] private var cancelCount = 0 override func viewDidLoad() { super.viewDidLoad() items = allItems updateTitle() let searchController = UISearchController(searchResultsController: nil) searchController.searchBar.delegate = self navigationItem.searchController = searchController navigationItem.preferredSearchBarPlacement = .integratedButton navigationItem.searchBarPlacementAllowsToolbarIntegration = false tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell") } private func updateTitle() { title = "Cancel presses: \(cancelCount)" } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { items.count } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) cell.contentConfiguration = { var config = cell.defaultContentConfiguration() config.text = items[indexPath.row] return config }() return cell } } extension ViewController: UISearchBarDelegate { func searchBarCancelButtonClicked(_ searchBar: UISearchBar) { print("searchBarCancelButtonClicked(_:)") cancelCount += 1 updateTitle() items = allItems tableView.reloadData() } } Thank you in advance!
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
2
Boosts
2
Views
371
Activity
2d
iOS App QuickType Bar Credit Card Autofill Not Working
According to this autofill credit card documentation we should be able to autofill credit card fields using the QuickType Bar for credit card fields, but it does not work. The QuickType Bar does not display for credit card fields (see screenshots) I have tested this on a physical device running iOS 27 (iPhone 16e), have added a card to the Autofill setting in the Wallet app, and have made sure my text fields have the correct textContentType values. I am able to autofill using the backup autofill menu, but it is less than ideal. It takes a minimum of 5 taps to autofill one field. It would be far less painful to just pull out the credit card and manually enter the information (see screenshot). Here is a link to my test project demonstrating the issue: https://drive.google.com/file/d/1wMGOUNhVnmt3rBAD0TSMf9NV39-JS9ij/view?usp=sharing
Replies
1
Boosts
0
Views
292
Activity
3d
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
1
Boosts
0
Views
381
Activity
4d
Best practice Replacement for Edit Button on iPhone Duo
On the iPhone Duo the standard "Edit" button for navigation bars is a text-based button, and text-based buttons are not pushed to the vertical toolbars on the Duo. This looks sometimes silly, if it is the only remaining button that can not be placed in the vertical toolbar and which has the result that an almost empty horizontal navigation bar must be kept visible as well. So I guess it would be good idea to have an icon-based replacement for the Editor button to avoid having two toolbars on the Duo. Is there a best practice for the icon to pick for such an edit button? Would be "square.and.pencil" (SF Symbols) a good choice? Or better the "pencil .circle", because the "square" one is often used for text-based input? Anything better?
Replies
4
Boosts
0
Views
975
Activity
4d
UITableView row reordering no longer works under macOS 27 with Mac Catalyst
Under macOS 27 using Mac Catalyst for a UIKit-based app, If you present a view controller with a table view as a form sheet or page sheet, row reordering fails to function. You can drag a row as expected but the blue movement bar never appears and if you drop the row it simply returns to its original location. The exact same view controller presented as a popover works just fine. The exact same view controller not presented as a modal (such as the app's root controller) works just fine. This is a serious bug affecting existing applications and being reported by paying customers. This has been reported as FB25038883 which includes a simple sample app demonstrating the issue.
Replies
0
Boosts
0
Views
292
Activity
4d
UINavigationController, Nav Bar buttons incorrect layout on iPhone Duo
When presenting a UINavigationController presented via UIViewControllerRepresentable in a sheet, the top nav bar buttons aren't correctly moving to the side bar on the front screen of the Duo. They do re-orient vertically, but they do so next to the side bar and not within it. What am I doing wrong? This is how I am setting the buttons: let trimButton = UIBarButtonItem(image: UIImage(systemName: "selection.pin.in.out"), style: .plain, target: self, action: #selector(enterTrimming(_:))) navigationItem.leftBarButtonItem = trimButton navigationItem.rightBarButtonItem = cancelButton navigationItem.leftBarButtonItem?.isEnabled = true navigationItem.rightBarButtonItem?.isEnabled = true
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
1
Boosts
0
Views
108
Activity
4d
How to automatically size a table's footer view
Hi, I would like to automatically vertically size the table's footer view so that it has a fixed pre-defined minimum height and maximum height that fills up the gap between the last cell and the bottom of the safe area. How can I do this? PS: It seems to be that the footer view's size is not included in the table view's content size, correct? Regards, Hardy
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
1
Boosts
0
Views
65
Activity
4d
iPhone Duo: navigation bar item briefly moves to vertical bar during fullScreen dismissal despite .disabled
On the folded iPhone Duo display, a navigation bar item briefly moves into the vertical bar during dismissal of a full-screen modal, then jumps back to the top. Both navigation controllers consistently return .disabled from preferredVerticalBarBehavior, with childForPreferredVerticalBarBehavior returning nil. Environment Xcode 27.1 RC (27A9275), iOS 27.1 SDK, iPhone Duo simulator, folded outer display in portrait. Steps to reproduce Run the single-file UIKit example below in a scene-based app with a generated launch screen and no main storyboard. Tap the gear button on the Home screen to present Settings using .fullScreen. Tap the close button on Settings. Watch the Home screen's gear button during the dismissal animation. Expected The gear button stays in the top horizontal navigation bar throughout the transition, because the vertical bar preference is .disabled on both navigation controllers. Actual For part of the dismissal, the gear button appears below the status icons in the right-hand vertical bar region. It then jumps back to the top horizontal bar. The underlying tab bar also temporarily moves from the bottom to the right before returning. This reproduces with an otherwise empty view, standard UIKit containers, and the default bar appearance. No app code changes safeAreaInsets, bar frames, or animation timing. During the presentation/dismissal cycle, the Home view's logged right safe-area inset changes from 0 to 88 points and back to 0. In our app, content constrained to the safe area visibly narrows during the same transient change. In separate comparisons, returning .disabled from the root tab controller and content controllers, or requesting setNeedsUpdateOfVerticalBarConfiguration in appearance callbacks, did not eliminate the issue. Changing the modal to .overFullScreen avoided it in the tested simulator, but changes the underlying view controller lifecycle. The example below intentionally keeps .fullScreen to reproduce the problem. Is this expected behavior, or a known UIKit issue? Is there a supported way to keep .disabled effective throughout a fullScreen presentation/dismissal? Has this been addressed in a newer SDK/runtime? I have not tested iOS 27.2 or a physical Duo device. Minimal reproduction (one Swift file): import UIKit @main final class DemoAppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, configurationForConnecting session: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { let configuration = UISceneConfiguration(name: "Demo", sessionRole: session.role) configuration.delegateClass = DemoSceneDelegate.self return configuration } } final class DemoSceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options: UIScene.ConnectionOptions) { guard let scene = scene as? UIWindowScene else { return } let home = DemoController() home.title = "首页" let navigation = DemoNavigationController(rootViewController: home) navigation.tabBarItem = UITabBarItem(title: "首页", image: UIImage(systemName: "house"), selectedImage: nil) let tabs = UITabBarController() if #available(iOS 18.0, *) { tabs.mode = .tabBar } tabs.viewControllers = [navigation] let window = UIWindow(windowScene: scene) window.rootViewController = tabs self.window = window window.makeKeyAndVisible() } } final class DemoNavigationController: UINavigationController { // 与音剪一致:导航容器固定横向栏,不转发给子页面。 @available(iOS 27.1, *) override var preferredVerticalBarBehavior: UIVerticalBarBehavior { .disabled } @available(iOS 27.1, *) override var childForPreferredVerticalBarBehavior: UIViewController? { nil } } final class DemoController: UIViewController { override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .systemBackground if title == "设置" { navigationItem.leftBarButtonItem = UIBarButtonItem(systemItem: .close, primaryAction: UIAction { [weak self] _ in self?.dismiss(animated: true) }) } else { navigationItem.rightBarButtonItem = UIBarButtonItem( image: UIImage(systemName: "gearshape"), primaryAction: UIAction { [weak self] _ in let settings = DemoController() settings.title = "设置" let navigation = DemoNavigationController(rootViewController: settings) navigation.modalPresentationStyle = .fullScreen self?.present(navigation, animated: true) }) } } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() print("[DuoDemo] \(title ?? "") safe=\(view.safeAreaInsets) nav=\(navigationController?.navigationBar.frame ?? .zero) tab=\(tabBarController?.tabBar.frame ?? .zero)") } }
Replies
0
Boosts
0
Views
204
Activity
4d
Supported way to return the user to the app they chose after a pause screen (App Intent from an "App is Opened" automation)
We're building a Screen Time / mindful-pause app for iOS 26–27. The user adds a Shortcuts personal automation "When is Opened" that runs our App Intent. The intent passes the trigger app's Bundle Identifier (from the trigger output) and shows a short pause screen. When the user taps "Continue", we want to take them back into that app — only the one app they chose, only after they tap. Is there a supported API to open another installed app when the user taps Continue, given its bundle identifier from the Shortcuts trigger? A DTS reply in 2024 said there was no supported way (thread 740707). Has anything changed in iOS 26/27? (Related feedback: FB15500695.) If not, is it acceptable to open the chosen app via a URL scheme it registers in its Info.plist, including a third-party sign-in callback scheme, purely to bring it to the foreground? Many apps register no URL scheme. Is there a recommended pattern — e.g. handing control back to Shortcuts so the automation or the "Open App" action opens the trigger app — without the "App is Opened" automation firing again in a loop? What's the recommended way to avoid that re-fire? We currently ignore it for a short time window. A minimal sample project reproduces this (App Intent, pause screen, Continue using UIApplication.open). Happy to share it. Xcode 27.0 (27A266a), iOS 27.0 (24A446).
Replies
0
Boosts
0
Views
50
Activity
4d
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
4
Boosts
0
Views
298
Activity
4d