Hello, I've a question about performance when trying to render lots of items coming from SwiftData via a @Query on a SwiftUI List. Here's my setup:
// Item.swift:
@Model final class Item: Identifiable {
var timestamp: Date
var isOptionA: Bool
init() {
self.timestamp = Date()
self.isOptionA = Bool.random()
}
}
// Menu.swift
enum Menu: String, CaseIterable, Hashable, Identifiable {
var id: String { rawValue }
case optionA
case optionB
case all
var predicate: Predicate<Item> {
switch self {
case .optionA: return #Predicate { $0.isOptionA }
case .optionB: return #Predicate { !$0.isOptionA }
case .all: return #Predicate { _ in true }
}
}
}
// SlowData.swift
@main
struct SlowDataApp: App {
var sharedModelContainer: ModelContainer = {
let schema = Schema([Item.self])
let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)
return try! ModelContainer(for: schema, configurations: [modelConfiguration])
}()
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(sharedModelContainer)
}
}
// ContentView.swift
struct ContentView: View {
@Environment(\.modelContext) private var modelContext
@State var selection: Menu? = .optionA
var body: some View {
NavigationSplitView {
List(Menu.allCases, selection: $selection) { menu in
Text(menu.rawValue).tag(menu)
}
} detail: {
DemoListView(selectedMenu: $selection)
}.onAppear {
// Do this just once
// (0..<15_000).forEach { index in
// let item = Item()
// modelContext.insert(item)
// }
}
}
}
// DemoListView.swift
struct DemoListView: View {
@Binding var selectedMenu: Menu?
@Query private var items: [Item]
init(selectedMenu: Binding<Menu?>) {
self._selectedMenu = selectedMenu
self._items = Query(filter: selectedMenu.wrappedValue?.predicate,
sort: \.timestamp)
}
var body: some View {
// Option 1: touching `items` = slow!
List(items) { item in
Text(item.timestamp.description)
}
// Option 2: Not touching `items` = fast!
// List {
// Text("Not accessing `items` here")
// }
.navigationTitle(selectedMenu?.rawValue ?? "N/A")
}
}
When I use Option 1 on DemoListView, there's a noticeable delay on the navigation. If I use Option 2, there's none. This happens both on Debug builds and Release builds, just FYI because on Xcode 16 Debug builds seem to be slower than expected: https://indieweb.social/@curtclifton/113273571392595819
I've profiled it and the SwiftData fetches seem blazing fast, the Hang occurs when accessing the items property from the List. Is there anything I'm overlooking or it's just as fast as it can be right now?
Explore the various UI frameworks available for building app interfaces. Discuss the use cases for different frameworks, share best practices, and get help with specific framework-related questions.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
We're building a UGC AR app and are leveraging App Clips to distribute AR experiences without app download.
Since earlier this week, many of our users are reporting sharing experiences as App Clip doesn't work anymore. They are getting the message "AppClip unavailable" on a little card. We attached a QR code to try it yourself and a link to a different experience. We tried with multiple experiences and on multiple devices already.
https://scenery.app/experience/1C925FDE-E49A-489B-BA14-58A4E532E645
Interestingly, we can't pinpoint the issue to an exact device or OS.
We tested on many devices and on most, the AppClip is being displayed as unavailable, stating "App Clip unavailable", whereas it works on a few. It all worked fine last week (before September 12th).
iPhone 13 Pro Max, iOS26: works
iPhone SE, iOS 17: works
iPhone 16 Pro, iOS 26: doesn't work
iPhone 12 Pro Max, iOS 26: doesn't work
iPhone 12 mini, iOS 18: does not work
iPad 9th gen, iOS 26: doesn't work
Please help. Our users are very dissatisfied as they expect this to work and it's a crucial feature.
We already filed a radar via Feedback assistant:
FB20303890
Hi,
I'm trying to toggle the visibility of an overlay by using hovering. However, I found onHover() and onContinuousHover() don't work on visionOS. Is it intended?
Is there an solution for my case?
Have a data model that sets certain fields as unique. If the user attempts to save a duplicate value, the save fails quietly with no indication to the user that the save failed. The program is on Mac OS 26.0.1
@Environment(\.modelContext) var modelContext
@Query private var typeOfContracts: [TypeOfContract]
@State private var typeName: String = ""
@State private var typeCode: String = ""
@State private var typeDescription: String = ""
@State private var contracts: [Contract] = []
@State private var errorMessage: String? = "Data Entered"
@State private var showAlert: Bool = false
var body: some View {
Form {
Text("Enter New Contract Type")
.font(.largeTitle)
.foregroundStyle(Color(.green))
.multilineTextAlignment(.center)
TextField("Contract Type Name", text: $typeName)
.frame(width: 800, height: 40)
TextField("Contract Type Code", text: $typeCode)
.frame(width: 800, height: 40)
Text("Contract Type Description")
TextEditor(text: $typeDescription)
.frame(width: 800, height: 200)
.scrollContentBackground(.hidden)
.background(Color.teal)
.font(.system(size: 24))
Button(action: {
self.saveContractType()
})
{
Text("Save new contract type")
}
}
}
func saveContractType() {
let typeOfContract = TypeOfContract(contracts: [])
typeOfContract.typeName = typeName
typeOfContract.typeCode = typeCode
typeOfContract.typeDescription = typeDescription
modelContext.insert(typeOfContract)
do {
try modelContext.save()
}catch {
errorMessage = "Error saving data: \(error.localizedDescription)"
}
}
}
I have tried to set alerts but Xcode tells me that the alerts are not in scope
Hi folks,
there's currently a known issue in TipKit due to which it won't show popover tips on buttons that are inside a SwiftUI ToolbarItem. For example, if you try this code, the popover tip will not appear:
ToolbarItem {
Button(action: {...}) {
Label("Tap here", systemImage: "gear")
}
.popoverTip(sampleTip)
}
There's an easy workaround for this issue. Just apply a style to the button. It can be any style. Some examples are bordered, borderless, plain and borderedProminent. Here's a fixed version of the above code:
ToolbarItem {
Button(action: {...}) {
Label("Tap here", systemImage: "gear")
}
.buttonStyle(.plain) // Adding this line fixes the issue.
.popoverTip(sampleTip)
}
Hope this helps anyone running into this issue.
I am coming from C#, where Forms and Controls are placed similar to Swift Storyboards. I have been trying to learn Storyboards, but keep running across tutorials regarding SwiftUI, and Storyboard examples are few. So the question becomes, "how do I position controls on a Form using SwiftUI?" See the example below.
I have run across many videos that use either horizontal or vertical positioning of controls, but these examples are usually very simple, with items occupying only the center portion of the screen. I get stuck on examples that are more complicated.
The example below only shows the controls for the upper part of a Form, with some type of textbox (Viewform) below making up the rest of the Form.
How does one make more complicated placement of controls with SwiftUI?
struct ContentView: View {
@State var isPresented = false
var body: some View {
Button {
isPresented.toggle()
} label: {
Text("Button")
}
.sheet(isPresented: $isPresented) {
SubView()
}
}
}
struct SubView: View {
@State var text = ""
var body: some View {
NavigationStack {
TextEditor(text: $text)
.toolbar {
ToolbarItemGroup(placement: .bottomBar) {
Button("Click") {
}
}
ToolbarItemGroup(placement: .keyboard) {
Button("Click") {
}
}
}
}
}
}
In the WWDC 2025 session "Build a UIKit app with the with the new design", at the 23:22 mark, the presenter says:
And finally, when you no longer need the glass on screen animate it out by setting the effect to nil.
The video shows a UIVisualEffectView whose effect is set to a UIGlassEffect animating away as its effect is set to nil. But when I do this in my app (or a sample app), setting effect to nil does not remove the glass appearance. Is this expected? Is the video out of date? Or is this a bug?
I had take screenshots by following code
let scenes = UIApplication.shared.connectedScenes
let windowScene = scenes.first as? UIWindowScene
let window = windowScene?.windows.first
self.uiImage = window?.rootViewController?.view!.getImage(rect: rect)
View has two views. One is ImageView contains some image and overlay of image detection results with .overlay. another view is InfoView contains several info and button which above code fired. on iOS 17, I can take screenshots as I saw, but on iOS26, missing on image of ImageView. Overlay(detected rectangle) in Imageview and InfView can be taken.
How can I take screenshots as I saw on iOS26?(iPad)
Do you guys know how to fix the render of the text in the accessory view ? If I force the color of text to be .black it work but it will break dark mode, but forcing it .black : .white on color scheme changes makes white to still adapt to what is behind it I have noticed that Apple Music doesn’t have that artifact and it seems to break when images are behind the accessory view
// MARK: - Next Routine Accessory
@available(iOS 26.0, *)
struct NetxRoutinesAccessory: View {
@ObservedObject private var viewModel = RoutineProgressViewModel.shared
@EnvironmentObject var colorSchemeManager: ColorSchemeManager
@EnvironmentObject var routineStore: RoutineStore
@EnvironmentObject var freemiumKit: FreemiumKit
@ObservedObject var petsStore = PetsStore.shared
@Environment(\.colorScheme) private var colorScheme
// Tab accessory placement environment
@Environment(\.tabViewBottomAccessoryPlacement) private var accessoryPlacement
// Navigation callback
var onTap: (() -> Void)?
@State private var isButtonPressed = false
/// Explicit black for light mode, white for dark mode
private var textColor: Color {
colorScheme == .dark ? .trueWhite : .trueBlack
}
/// Returns true when the accessory is in inline/minimized mode
private var isInline: Bool {
accessoryPlacement == .inline
}
var body: some View {
accessoryContent()
.onTapGesture {
onTap?()
}
}
private func accessoryContent() -> some View {
HStack(spacing: 12) {
// Content with smooth transitions
VStack(alignment: .leading, spacing: 2) {
if viewModel.totalTasks == 0 {
Text(NSLocalizedString("Set up routines", comment: "Routines empty state"))
.font(.subheadline.weight(.medium))
.foregroundColor(textColor)
} else if let next = viewModel.nextRoutineTask() {
HStack(spacing: 4) {
Text(NSLocalizedString("Next", comment: "Next routine prefix"))
.font(.caption)
.foregroundColor(textColor)
Text("•")
.font(.caption)
.foregroundColor(textColor)
Text(next.routine.name)
.font(.subheadline.weight(.medium))
.foregroundColor(textColor)
.lineLimit(1)
}
.id("routine-\(next.routine.id)-\(next.time)")
.transition(.opacity.combined(with: .move(edge: .leading)))
HStack(spacing: 4) {
Text(viewModel.petNames(for: next.routine.petIDs))
.font(.caption)
.foregroundColor(textColor)
Text("•")
.font(.caption)
.foregroundColor(textColor)
Text(Routine.displayTimeFormatter.string(from: next.time))
.font(.caption.weight(.medium))
.foregroundColor(colorSchemeManager.accentColor ?? .blue)
}
.id("time-\(next.routine.id)-\(next.time)")
.transition(.opacity.combined(with: .move(edge: .leading)))
} else {
// All tasks completed
Text(NSLocalizedString("All done for today!", comment: "All routines completed"))
.font(.subheadline.weight(.medium))
.foregroundColor(textColor)
.transition(.opacity.combined(with: .scale))
Text("\(viewModel.completedTasks)/\(viewModel.totalTasks) " + NSLocalizedString("tasks", comment: "Tasks count suffix"))
.font(.caption)
.foregroundColor(textColor)
}
}
.animation(colorSchemeManager.reduceMotion ? nil : .snappy(duration: 0.3), value: viewModel.completedTasks)
.animation(colorSchemeManager.reduceMotion ? nil : .snappy(duration: 0.3), value: viewModel.progress)
}
.padding()
.contentShape(.rect)
.animation(colorSchemeManager.reduceMotion ? nil : .snappy(duration: 0.35), value: viewModel.completedTasks)
}
}
Topic:
UI Frameworks
SubTopic:
SwiftUI
After updating to Sonoma, the following is logged in the Xcode console when an editable text field becomes key. This doesn't occur on any text field, but it seems to happen when the text field is within an NSPopover or an NSSavePanel.
ViewBridge to RemoteViewService Terminated: Error Domain=com.apple.ViewBridge Code=18 "(null)" UserInfo={com.apple.ViewBridge.error.hint=this process disconnected remote view controller -- benign unless unexpected, com.apple.ViewBridge.error.description=NSViewBridgeErrorCanceled}
What does this mean?
Topic:
UI Frameworks
SubTopic:
AppKit
This new modifier is supposedly backported to iOS 17, but on attempting to use it on the latest iOS 18.5, this happens:
Symbol not found: _$s7SwiftUI17EnvironmentValuesV33_navigationIndicatorVisibilityABIAA0G0OvpMV
This happens with any usage of the modifier. An availability check won't save you either.
The cruelest part of this is that I only need the modifier on iOS 26, lmao.
Am I just missing something?
Topic:
UI Frameworks
SubTopic:
SwiftUI
We're trying to implement a backup/restore data feature in our business productivity iPad app using UIDocumentPickerViewController and AppleArchive, but discovered odd behavior of [UIDocumentPickerViewController initForOpeningContentTypes: asCopy:YES] when reading large archive files from a USB drive.
We've duplicated this behavior with iPadOS 16.6.1 and 17.7 when building our app with Xcode 15.4 targeting minimum deployment of iPadOS 16. We haven't tested this with bleeding edge iPadOS 18.
Here's our Objective-C code which presents the picker:
NSArray* contentTypeArray = @[UTTypeAppleArchive];
UIDocumentPickerViewController* docPickerVC = [[UIDocumentPickerViewController alloc] initForOpeningContentTypes:contentTypeArray asCopy:YES];
docPickerVC.delegate = self;
docPickerVC.allowsMultipleSelection = NO;
docPickerVC.shouldShowFileExtensions = YES;
docPickerVC.modalPresentationStyle = UIModalPresentationPopover;
docPickerVC.popoverPresentationController.sourceView = self.view;
[self presentViewController:docPickerVC animated:YES completion:nil];
The UIDocumentPickerViewController remains visible until the selected external archive file has been copied from the USB drive to the app's local tmp sandbox. This may take several seconds due to the slow access speed of the USB drive. During this time the UIDocumentPickerViewController does NOT disable its tableview rows displaying files found on the USB drive. Even the most patient user will tap the desired filename a second (or third or fourth) time since the user's initial tap appears to have been ignored by UIDocumentPickerViewController, which lacks sufficient UI feedback showing it's busy copying the selected file.
When the user taps the file a second time, UIDocumentPickerViewController apparently begins to copy the archive file once again. The end result is a truncated copy of the selected file based on the time between taps. For instance, a 788 MB source archive may be copied as a 56 MB file. Here, the UIDocumentPickerDelegate receives a 56 MB file instead of the original 788 MB of data.
Not surprisingly, AppleArchive fails to decrypt the local copy of the archive because it's missing data. Instead of failing gracefully, AppleArchive crashes in AAArchiveStreamClose() (see forums post 765102 for details).
Does anyone know if there's a workaround for this strange behavior of UIDocumentPickerViewController?
I've discovered an issue with using iOS 16's Transferable drag-and-drop APIs for SwiftUI. The dropDestination modifier does not work when applied to a subview of a List.
This code below will not work, unless you replace the List with a VStack or any other container (which, of course, removes all list-specific rendering).
The draggable modifier will still work and the item will drag, but the dropDestination view won't react to it and neither closure will be called.
struct MyView: View {
var body: some View {
List {
Section {
Text("drag this title")
.font(.largeTitle)
.draggable("a title")
}
Section {
Color.pink
.frame(width: 400, height: 400)
.dropDestination(for: String.self) { receivedTitles, location in
true
} isTargeted: {
print($0)
}
}
}
}
}
Has anyone encountered this bug and perhaps found a workaround?
Following on from this thread: https://developer.apple.com/forums/thread/805037 my list of items is now correctly maintaining state (no more disappearing rows), but I'm now hitting a really annoying issue: Every time something changes - even just changing the dark mode of the device - the entire list of items is refreshed, and the list jumps back to the top.
A simple representation:
// modelData.filteredItems is either all items or some items, depending on whether the user is searching
List {
ForEach(modelData.filteredItems) { item in
ItemRow(item: item)
}
}
When the user isn't searching, filteredItems has everything in it. When they turn on search, I filter and sort the data in place:
// Called when the user turns on search, or when the searchString or searchType changes
func sortAndFilterItemsInModelData() {
modelData.filteredItems.removeAll() // Remove all items from the filtered array
modelData.filteredItems.append(contentsOf: modelData.allItems) // Add all items back in
let searchString: String = modelData.searchString.lowercased()
switch(modelData.searchType) {
case 1:
// Remove all items from the filtered array that don't match the search string
modelData.filteredItems.removeAll(where: { !$0.name.lowercased().contains(searchString) })
...
}
// Sorting
switch(modelData.sortKey) {
case sortKeyDate:
modelData.sortAscending ? modelData.filteredItems.sort { $0.date < $1.date } : modelData.filteredItems.sort { $0.date > $1.date } // Sorts in place
...
}
}
The method doesn't return anything because all the actions are done in place on the data, and the view should display the contents of modelData.filteredItems.
If you're searching and there are, say 10 items in the list and you're at the bottom of the list, then you change the search so there are now 11 items, it jumps back to the top rather than just adding the extra ItemRow to the bottom. Yes, the data is different, but it hasn't been replaced; it has been altered in place.
The biggest issue here is that you can simply change the device to/from Dark Mode - which can happen automatically at a certain time of day - and you're thrown back to the top of the list. The array of data hasn't changed, but SwiftUI treats it as though it has.
There's also a section in the List that can be expanded and contracted. It shows or hides items of a certain type. When I expand it, I expect the list to stay in the same place and just show the extra rows, but again, it jumps to the top. It's a really poor user experience.
Am I doing something wrong (probably, yes), or is there some other way to retain the scroll position in a List? The internet suggests switching to a LazyVStack, but I lose left/right swipe buttons and the platform-specific styling.
Thanks.
I'm struggling to understand whether TextField handles undo by itself, or how to properly handle it myself.
In a macOS app with a SwiftUI lifecycle, in a DocumentGroup scene, I'm using both TextEditors and Textfields. The text editors handle undo out of the box, with undo coalescing.
The text fields seem not to. However, on occasion, they do create undo points, leaving me confused as to what conditions are needed for that to happen.
Is there a way to reliably get text fields to handle undo on their own? Or, how should I implement typing undo, including undo coalescing, manually?
Topic:
UI Frameworks
SubTopic:
SwiftUI
When I create a SwiftUI toolbar item with placement of .keyboard on iOS 26, the item appears directly on top of and in contact with the keyboard. This does not look good visually nor does it match the behavior seen in Apple's apps, such as Reminders. Adding padding to the contents of the toolbar item only expands the size of the item but does not separate the capsule background of the item from the keyboard. How can I add vertical padding or spacing to separate the toolbar item capsule from the keyboard?
Topic:
UI Frameworks
SubTopic:
SwiftUI
Hi,
I’m seeing a crash when running my app on iOS 18 simulators or devices using Xcode 26 beta 3.
My app’s minimum deployment target is iOS 17, and the crash does not happen when running from Xcode 16.4.
The crash occurs specifically at this line:
return UIStoryboard(name: storyboard.rawValue, bundle: nil)
.instantiateViewController(withIdentifier: view.rawValue)
Crash Details:
** Terminating app due to uncaught exception 'NSInvalidUnarchiveOperationException', reason: 'Could not instantiate class named _TtGC5UIKit17UICoreHostingViewVCS_21ToolbarVisualProvider8RootView_ because no class named _TtGC5UIKit17UICoreHostingViewVCS_21ToolbarVisualProvider8RootView_ was found; the class needs to be defined in source code or linked in from a library (ensure the class is part of the correct target)'
*** First throw call stack:
(0x191c3321c 0x18f0cdabc 0x191c91ea0 0x19d740774 0x19d740a18 0x19d740cac 0x194626680 0x194dbc784 0x19d740890 0x19d740cac 0x1949aadd8 0x19d740890 0x19d740a18 0x19d740cac 0x194802e24 0x1945f008c 0x194ed1808 0x107a8bfa0 0x107a8c05c 0x1945ec128 0x19d740890 0x19d740cac 0x1945eba60 0x19d740890 0x19d740a18 0x19d740cac 0x1945f07dc 0x1945eaea4 0x19492ee80 0x10763de00 0x1076e56fc 0x1076e5674 0x1076e5e04 0x19496108c 0x194f9b9a0 0x1949072c4 0x194f998cc 0x194f9af04 0x19445139c 0x19445ac28 0x194467508 0x1079afaec 0x1079aff5c 0x1944189a0 0x194417be4 0x1944114e4 0x194411404 0x194410ab4 0x19440c1e4 0x191b28a8c 0x191b288a4 0x191b28700 0x191b29080 0x191b2ac3c 0x1ded09454 0x19453d274 0x194508a28 0x1073564f4 0x1b89fff08)
terminating due to uncaught exception of type NSException
The crash occurs immediately at app launch, when attempting to load a storyboard-based UITabBarController.
Works as expected on:
Xcode 16.4 + iOS 18 (simulator/device)
Xcode 26 beta 3 + iOS 26 (simulator/device)
Running from Xcode 26 beta 3 onto iOS 18 simulators or devices and it immediate crash from the particular storyboard
Setup:
Xcode: 26 beta 3
macOS: 15.5
iOS Simulators: iOS 18.5
Minimum deployment target: iOS 17
UIKit-based app (not using SwiftUI)
No custom toolbars or host views in use explicitly
Is this a known compatibility issue when building with the iOS 26 SDK and running on iOS 18?
Are there any workarounds or recommendations for running apps targeting iOS 17+ on iOS 18 simulators when using Xcode 26?
Navigation Title no longer showing for first Tab in iOS/iPadOS 26 (Directives) in my app Starship SE Corps when running is Xcode 26 simulator and on iPad device itself running iPadOS 26 beta.
Launch app
Notice Navigation Title “Directives” is missing from top tab in Sidebar and Floating Tab View (iPad) and TabView (iOS).
Navigate to other tabs and Navigation Titles appear as expected.
Worked fine (as expected) in iOS/iPadOS 18.5, but broken in iOS/iPadOS 26.
Reference Feedback: FB17987650
I’m developing a share extension for iOS 26 with Xcode 26. When the extension’s sheet appears, it always shows a full white background, even though iOS 26 introduces a new “Liquid Glass” effect for partial sheets.
Expected:
The sheet background should use the iOS 26 glassmorphism effect as seen in full apps.
Actual behavior:
Custom sheets in my app get the glass effect, but the native system sheet in the share extension always opens as plain white.
Steps to reproduce:
Create a share extension using UIKit
Present any UIViewController as the main view
Set modalPresentationStyle = .pageSheet (or leave as default)
Observe solid white background, not glassmorphism
Sample code:
swift
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .clear
preferredContentSize = CGSize(width: UIScreen.main.bounds.width, height: 300)
}
Troubleshooting attempted:
Tried adding UIVisualEffectView with system blur/materials
Removed all custom backgrounds
Set modalPresentationStyle explicitly
Questions:
Is it possible to enable or force the Liquid Glass effect in share extensions on iOS 26?
Is this a limitation by design or a potential bug?
Any workaround to make extension sheet backgrounds match system glass appearance?