I was reading over the documentation of the CellProvider struct for the diffable data source initialiser, and the CellProvider is defined as a closure which takes three arguments, a table view, an index path, and an item identifier. My question is, who vends the index path and the item identifier to this closure? My thinking is that it is the data source who vends these items because it adopts the UITableViewDataSource protocol which acts as the source of data for this view.
UIKit
RSS for tagConstruct and manage graphical, event-driven user interfaces for iOS or tvOS apps using UIKit.
Posts under UIKit tag
200 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
Starting with iOS 26 beta, I'm encountering an intermittent crash in production builds related to Auto Layout and background threading. This crash did not occur on iOS 18 or earlier and has become reproducible only on devices running iOS 26 betas.
We have already performed a thorough audit of our code:
• Verified that all UIKit view hierarchy and layout mutations occur on the main thread.
• Re-tested with strict logging—confirmed all remaining layout/constraint/view updates are performed on the main thread.
• No third-party UI SDKs are used in the relevant flow.
Despite that, the crash still occurs and always from a background thread, during internal UIKit layout commits.
Fatal Exception: NSInternalInconsistencyException
Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread.
0 MyApp 0x7adbc8 FIRCLSProcessRecordAllThreads + 172
1 MyApp 0x7adfd4 FIRCLSProcessRecordAllThreads + 1208
2 MyApp 0x7bc4b4 FIRCLSHandler + 56
3 MyApp 0x7bc25c __FIRCLSExceptionRecord_block_invoke + 100
4 libdispatch.dylib 0x1b7cc _dispatch_client_callout + 16
5 libdispatch.dylib 0x118a0 _dispatch_lane_barrier_sync_invoke_and_complete + 56
6 MyApp 0x7bb1f0 FIRCLSExceptionRecord + 224
7 MyApp 0x7bbd1c FIRCLSExceptionRecordNSException + 456
8 MyApp 0x7badf4 FIRCLSTerminateHandler() + 396
9 Intercom 0x86684 IntercomSDK_sentrycrashcm_cppexception_getAPI + 308
10 libc++abi.dylib 0x11bdc std::__terminate(void (*)()) + 16
11 libc++abi.dylib 0x15314 __cxa_get_exception_ptr + 86
12 libc++abi.dylib 0x152bc __cxxabiv1::failed_throw(__cxxabiv1::__cxa_exception*) + 90
13 libobjc.A.dylib 0x3190c objc_exception_throw + 448
14 CoreAutoLayout 0x13a4 -[NSISEngine optimize] + 314
15 CoreAutoLayout 0x1734 -[NSISEngine _optimizeWithoutRebuilding] + 72
16 CoreAutoLayout 0x1404 -[NSISEngine optimize] + 96
17 CoreAutoLayout 0xee8 -[NSISEngine performPendingChangeNotifications] + 104
18 UIKitCore 0x27ac8 -[UIView(Hierarchy) layoutSubviews] + 136
19 UIKitCore 0xfe760 -[UIWindow layoutSubviews] + 68
20 UIKitCore 0x234228 -[UITextEffectsWindow layoutSubviews] + 44
21 UIKitCore 0x27674 -[UIImageView animationImages] + 912
22 UIKitCore 0x28134 -[UIView(Internal) _viewControllerToNotifyOnLayoutSubviews] + 40
23 UIKitCore 0x18c2898 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2532
24 QuartzCore 0xabd98 CA::Layer::perform_update_(CA::Layer*, CALayer*, unsigned int, CA::Transaction*) + 116
25 QuartzCore 0x8e810 CA::Layer::update_if_needed(CA::Transaction*, unsigned int, unsigned int) + 600
26 QuartzCore 0xad45c CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 200
27 QuartzCore 0x6e30c CA::Context::commit_transaction(CA::Transaction*, double, double*) + 540
28 QuartzCore 0x9afc4 CA::Transaction::commit() + 644
29 QuartzCore 0x16974c CA::Transaction::release_thread(void*) + 180
30 libsystem_pthread.dylib 0x4c28 _pthread_tsd_cleanup + 620
31 libsystem_pthread.dylib 0x4998 _pthread_exit + 84
32 libsystem_pthread.dylib 0x5e3c pthread_atfork + 54
33 libsystem_pthread.dylib 0x1440 _pthread_wqthread + 428
34 libsystem_pthread.dylib 0x8c0 start_wqthread + 8
Any ideas?
Hi,
I am running iOS Simulator on iOS 26 and I am trying to change unselectedItemTintColor of UITabBarItem in my TabBarViewController but it did not work when I tried following ways:
Setting an iconColor through UITabBarAppearance() class
Setting unselected item tint color like tabBar.unselectedItemTintColor = .black
As an example attached file, I would like to set Settings tab's item color (icon + title) with different one when it is unselected.
I'm very happy with the new badge property of UIBarButtonItem, but unfortunately it doesn't work yet on a UIToolbar object.
The following code does change the tint color of the button to pink, which proves the button object exists, but there is no visible badge after running the code:
if let button = toolbarItems?.first {
button.badge = .count(123) // Does nothing
button.tintColor = .systemPink // Works
}
Do I overlook something, or is this just not implemented yet? Or is this limitation 'by design'? (That would be a MAJOR disappointment)
Hello,
I have an existing AUv3 instrument plugin. In the plug in, users can access files (audio files, song projects) via a UIDocumentPickerViewController
In Logic Pro, (and some other hosts, but not all), the document picker is unable to receive touches, while a keyboard case is attached to the iPad.
Removing the case (this is an Apple brand iPad case) allows the interactions to resume and allows me to pick files in the usual way.
One of my users reports this non-responsive behavior occurs even after disconnecting their keyboard.
I have fiddled with entitlements all day, and have determined that is not the issue, since the keyboard disconnection appears to fix it every time for me.
Here is my, very boilerplate, presentation code :
guard let type = UTType("com.my.type") else {
return
}
let fileBrowser = UIDocumentPickerViewController(forOpeningContentTypes: [type])
fileBrowser.overrideUserInterfaceStyle = .dark
fileBrowser.delegate = self
fileBrowser.directoryURL = myFileFolderURL()
self.present(fileBrowser, animated: true) {
I work on a universal app that targets both iPhone and iPad. Our iPad app currently requires full screen. When testing on the latest iPadOS 26 beta, we see the following warning printed to the console:
Update the Info.plist: 1) `UIRequiresFullScreen` will soon be ignored. 2) Support for all orientations will soon be required.
It will take a fair amount of effort to update our app to properly support presentation in a resizable window. We wanted to gauge how urgent this change is. Our testing has shown that iPadOS 26 supports our app in a non-resizable window.
Can someone from Apple provide any guidance as to how soon “soon” is? Will UIRequiresFullScreen be ignored in iPadOS 26? Will support for all orientations be required in iPadOS 26?
I want to understand what the recommended way is for string interoperability between swift and c++. Below are the 3 ways to achieve it. Approach 2 is not allowed at work due to restrictions with using std libraries.
Approach 1:
In C++:
char arr[] = "C++ String";
void * cppstring = arr;
std::cout<<"before:"<<(char*)cppstring<<std::endl; // C++ String
// calling swift function and passing the void buffer to it, so that swift can update the buffer content
Module1::SwiftClass:: ReceiveString (cppstring, length);
std::cout<<"after:"<<(char*)cppstring<<std::endl; // SwiftStr
In Swift:
func ReceiveString (pBuffer : UnsafeMutableRawPointer , pSize : UInt ) -> Void
{
// to convert cpp-str to swift-str:
let swiftStr = String (cString: pBuffer.assumingMemoryBound(to: Int8.self));
print("pBuffer content: \(bufferAsString)");
// to modify cpp-str without converting:
let swiftstr:String = "SwiftStr"
_ = swiftstr.withCString { (cString: UnsafePointer<Int8>) in
pBuffer.initializeMemory(as: Int8.self, from: cString, count: swiftstr.count+1)
}
}
Approach 2:
The ‘String’ type returned from a swift function is received as ‘swift::String’ type in cpp. This is implicitly casted to std::string type. The std::string has the method available to convert it to char *.
void
TWCppClass::StringConversion ()
{
// GetSwiftString() is a swift call that returns swift::String which can be received in std::string type
std::string stdstr = Module1::SwiftClass::GetSwiftString ();
char * cstr = stdstr.data ();
const char * conststr= stdstr.c_str ();
}
Approach 3:
The swift::String type that is obtained from a swift function can be received in char * by directly casting the address of the swift::String. We cannot directly receive a swift::String into a char *.
void
TWCppClass::StringConversion ()
{
// GetSwiftString() is a swift call that returns swift::String
swift::String swiftstr = Module1::SwiftClass::GetSwiftString ();
// obtaining the address of swift string and casting it into char *
char * cstr = (char*)&swiftstr;
}
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?
Does anyone have any documentation for how to achieve the floating search tab item in UIKit apps that use UITabBarController?
The Liquid Glass UIKit video had code for minimizing the tab bar on scroll down, but I didn't see anything on keeping the search button locked to the bottom trailing edge (as in this screenshot below).
I’ve implemented a basic custom view controller presentation: the presented view controller slides up from the bottom in a manner similar to UISheetPresentationController, and can be dismissed by tapping the dimming view added on top of the presenting view controller.
I want my custom presentation to be interruptible, so the user should be able to tap the dimming view while the presentation transition is in progress to smoothly convert the presentation transition into a dismissal transition. I’m using additive spring animations (by virtue of UIViewPropertyAnimator) here to make the change in direction less jarring.
Unfortunately, it seems that the interruption-triggered dismissal transition is abruptly terminated by the system based on some kind of timer. The later in the presentation transition I tap the dimming view, the earlier the dismissal transition is terminated.
Steps to reproduce
After launching the test project:
Tap the “Present” button.
Tap the dimming view just before the transition completes.
The test project includes a screen recording of the broken behavior.
I my App I use the sheetPresentationController to get a sheet that sits on top of the main view (a Map) and that can be slided up and down, similar to the Maps or FindMy Apps.
This works great with iOS 18 and older. But under iOS 26 Beta I see issues, especially on the iPad.
When the window is small (iPhone or compact size class on iPad), changing the height of the sheet works as expected, the sheet window is attached to the bottom of the screen and I can slide it up and down. But when the App window is wider (regular size class on the iPad), the sheet is shown at the left (as expected), but it is no longer attached to the bottom of the screen, there's a very large (but constant) gap between the bottom of the App window and the bottom of the sheet. I haven't found a way to minimize the gap, the sheet window seems to totally ignore the vertical position and size of the "sourceView" to which the sheet should be attached to (it still evaluates the horizontal position, so I can move the sheet to the right, but the vertical position can't be controlled anymore). The Maps App or FindMy Apps do not show this issue, also iOS 18 and older do not show this issue.
Is this normal or can I do something to prevent this? The sheet should always be positioned to the bottom left corner of the App window,
Another problem is the window background with a UIGlassContainer effect. In the Apple Maps App the sheet looses its glass effect transparency under iOS 26 when the sheet is fully expanded. The FindMy does not have this issue, here the glass effect/transparency is always present. In my App the background shows the glass effect when the window is not fully expanded when the overall App window is above a certain height (like the Apple Maps App), but when the App window is below a certain height then it is the opposite way: fully expanded it shows the glass effect and at smaller heights it is opaque. Why is this the case?
How can I get the behavior of the FindMy App where the sheet window keeps its transparent glass effect in all cases? I do not want to have it changing its appearance depending of the height of the sheet.
I can "solve" some of the issues when presenting the "sheet" as popover (via popoverPresentationController) and from within the popoverPresentationController use the adaptiveSheetPresentationController property to get the UISheetPresentationController (instead of directly using the sheetPresentationController property). In small App windows (iPhone or compact size class) it works exactly as when directly using sheetPresentationController. With larger App windows (iPad and regular size class) the sheet will be attached to the bottom of the App window (as expected) and the glass effect is always present. However in this case the detents which define the allowed heights of the sheet window will be always ignored, the window seems to have always the maximum height (minus some safe areas), Even when using the preferredContentSize property to set the size, only the width is respected, but never the height.
Is there any way to get this working? Is this supposed to work this way or is this still a beta issue?
I noticed that trying to access safeAreaInsets from the active window causes an infinite run loop.
This issue appeared after updating to Beta 3.
Here’s an example of the code:
extension UIDevice {
var safeAreaInsets: UIEdgeInsets {
guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let window = windowScene.windows.first(where: { $0.isKeyWindow }) else {
return .zero
}
return window.safeAreaInsets
}
}
The return doesn’t happen because it ends up in some kind of recursion.
The documentation for UIListContentConfiguration states that I can get the default content configuration of a UICollectionViewCell by getting the cells default content configuration. In practice, however, this presents an error in the compiler:
let choiceRegistration = UICollectionView.CellRegistration<UICollectionViewCell, SurveyItem> { cell, indexPath, item in
cell.configurationUpdateHandler = { cell, state in
switch item.type {
case .choice(let letter, let text):
cell.defaultContentConfiguration()
...
}
The error shown when calling cell.defaultContentConfiguration() is Value of type 'UICollectionViewCell' has no member 'defaultContentConfiguration'. Instead, I need to initialise a content configuration using UIListContentConfiguration.cell() to get the default content configuration.
This needs to be reflected in the documentation in UIKit.
Error:
Fatal error: init(coder:) has not been implemented
File:
UIKitCore/UICoreHostingView.swift:54
Stack Trace Snippet:
swift
Copy
Edit
UIKitCore/UICoreHostingView.swift:54: Fatal error: init(coder:) has not been implemented
Can't show file for stack frame: <DBGLldbStackFrame: 0x10ca74560> - stackNumber: 23
name: @objc ThemeableViewController.init(coder:).
The file path does not exist on the file system: /
I'm using Swift to display some text in the middle of the screen, but I'm doing this programmatically instead of using the layout designer.
So I'm starting with my version of a UILabel:
class GenericLabel: UILabel
I'm then creating one of these objects:
let label = GenericLabel(frame: CGRect.zero)
label.processResponse(componentDictionary )
view.addSubview(label)
The processResponse function will set the text value, the font, fontsize, and set the bounds for where the text should be displayed on the screen. Currently I'm just wanting to position the text in the centre of the screen. During this process I send some messages to the console, like my calculation of the width and height and the bounds value. The console includes this:
GenericLabel: default = centrex and centrey
Utils:setSize: parent view bounds = (0.0, 0.0, 402.0, 874.0)
Utils:setSize: obj size = (85.33333333333333, 20.333333333333332)
Utils.setSize: centrey myframe.origin.y = 426.8333333333333
Utils.setSize: centrex myframe.origin.x = 158.33333333333334
Utils:setSize: myframe is now set to = (158.33333333333334, 426.8333333333333, 85.33333333333333, 20.333333333333332)
self.frame set to (158.33333333333334, 426.8333333333333, 85.33333333333333, 20.333333333333332)
Finally I set this frame to my GenericLabel
self.frame = Utils.setSize(["centrex":0, "centrey":0], for: self)
// You can see this message in the console above
print("self.frame set to \(self.frame)")
Unfortunately the text appears at (0,0) as in this screenshot.
Why is the frame not working?
Is there some setting overriding the frame?
I’m using the new preferredTransition = .zoom(...) API introduced in iOS 18.
Here’s a simplified version of what I do on app startup:
let listVC = CollectionViewController(collectionViewLayout: layout)
let detailVC = DetailViewController()
detailVC.preferredTransition = .zoom(sourceViewProvider: { context in
let indexPath = IndexPath(row: 0, section: 0)
let cell = listVC.collectionView.cellForItem(at: indexPath)
return cell
})
let nav = UINavigationController()
nav.setViewControllers([listVC, detailVC], animated: false)
window?.rootViewController = nav
window?.makeKeyAndVisible()
This is meant to restore the UI state from a previous session — the app should launch directly into the DetailViewController.
The Problem
When I launch the app with setViewControllers([listVC, detailVC], animated: false), the transition from listVC to detailVC appears correctly (i.e., no animation, as intended), but the drag-to-dismiss gesture does not work. The back button appears, and tapping it correctly triggers the zoom-out transition back to the cell, so the preferredTransition = .zoom(...) itself is properly configured.
Interestingly, if I delay the push with a DispatchQueue.main.async and instead do:
nav.setViewControllers([listVC], animated: false)
DispatchQueue.main.async {
nav.pushViewController(detailVC, animated: true)
}
…then everything works perfectly — including the interactive swipe-to-dismiss gesture — but that introduces an unwanted visual artifact: the user briefly sees the listVC, and then it pushes to detailVC, which I’m trying to avoid.
My Question
Is there a way to enable the swipe-to-dismiss gesture when using setViewControllers([listVC, detailVC], animated: false)
It can be very confusing for users if swipe-to-dismiss only works in certain cases inconsistently.
Thanks
When compiled on Xcode 16.4.0:
When compiled on Xcode 26:
The code:
import SwiftUI
struct SearchBarController: UIViewRepresentable {
@Binding var text: String
var placeholderText: String
class Coordinator: NSObject, UISearchBarDelegate {
@Binding var text: String
init(text: Binding<String>) {
_text = text
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
text = searchText
}
}
func makeUIView(context: Context) -> UISearchBar {
let searchBar = UISearchBar(frame: .zero)
searchBar.delegate = context.coordinator
searchBar.placeholder = placeholderText
searchBar.searchBarStyle = .minimal
return searchBar
}
func updateUIView(_ uiView: UISearchBar, context: Context) {
uiView.text = text
}
func makeCoordinator() -> SearchBarController.Coordinator {
return Coordinator(text: $text)
}
}
Starting on iOS 26 Beta 3, any UIVisualEffectView using a UIGlassEffect will have a default corner radius that cannot be modified by using UIVisualEffectView's layer.cornerRadius. This was working on Beta 1 and Beta 2.
On WWDC25 "Build a UIKit app with the new design", a UIVisualEffectView property called cornerConfiguration is used as example for changing the effect's corner radius, but this property does not seem to be available on any of the beta versions.
Is there any other way to update the UIGlassEffect corner radius on UIKit?
Hi,
In iOS 26, pushing or popping a view controller via UINavigationController shows a rounded corner effect during transition. This seems to be a new system feature.
Is there a way to disable this and restore the previous full-rectangle style, as seen in earlier iOS versions (e.g. iOS 18)? Any official API or recommended approach?
Thanks!
When using UIPageViewController inside a UITabBarController on iOS 26 with Liquid Glass adoption, visiting the PageViewController tab applies a blur effect to the navigation bar and tab bar even though the current child view controller of the pageView is not scrollable and does not reach behind these bars.
Questions:
Is this the expected behavior that the pageview's internal scroll view causes the bars to blur regardless of the page view's child content’s scrollability?
If so, is there an official way to make the blur effect appear only when the pageview's current child view controller actually scrolls behind the navigation bar or tab bar, and not in static cases?
Tried the same in SwiftUI using TabView and TabView with page style. Facing the same issue there as well.
Sample screenshots for reference,
Sample SwiftUI code,
struct TabContentView: View {
var body: some View {
TabView {
// First Tab: Paging View
PagingView()
.tabItem {
Label("Pages", systemImage: "square.fill.on.square.fill")
}
// Second Tab: Normal View
NavigationStack {
ListView()
}
.tabItem {
Label("Second", systemImage: "star.fill")
}
// Third Tab: Normal View
PageView(color: .blue, text: "Page 3")
.tabItem {
Label("Third", systemImage: "gearshape.fill")
}
}
.ignoresSafeArea()
}
}
struct PagingView: View {
var body: some View {
TabView {
PageView(color: .red, text: "Page 1")
PageView(color: .green, text: "Page 2")
PageView(color: .blue, text: "Page 3")
}
.tabViewStyle(.page) // Enables swipe paging
.indexViewStyle(.page(backgroundDisplayMode: .always))
.ignoresSafeArea()// Dots indicator
}
}