Hi,
When using SwiftUI ‘List’ with a large number of elements (4000+), I noticed a significant performance issue if extracting the views inside the ‘ForEach’ block into their own subview class. It affects scrolling performance, and using the scroll handle in the scrollbar causes stutters and beachballs. This seems to happen on macOS only ... the same project works fine on iOS.
Here's an example of what I mean:
List (selection: $multiSelectedContacts) {
ForEach(items) { item in
// 1. this subview is the problem ... replace it with the contents of the subview, and it works fine
PlainContentItemView(item: item)
// 2. Uncomment this part for it to work fine (and comment out PlainContentItemView above)
/*HStack {
if let timestamp = item.timestamp, let itemNumber = item.itemNumber {
Text("\(itemNumber) - \(timestamp, formatter: itemFormatter)")
}
}*/
}
}
struct PlainContentItemView: View {
let item: Item
var body: some View {
HStack {
if let timestamp = item.timestamp, let itemNumber = item.itemNumber {
Text("\(itemNumber) - \(timestamp, formatter: itemFormatter)")
}
}
}
}
Item is a NSManagedObject subclass, and conforms to Identifiable by using the objectID string value.
With this, scrolling up and down using the scrolling handle, causes stuttering scrolling and can beachball on my machine (MacBook Pro M1).
If I comment out the ‘PlainContentItemView’ and just use the HStack directly (which is what was extracted to ‘PlainContentItemView’), the performance noticeably improves, and I can scroll up and down smoothly.
Is this just a bug with SwiftUI, and/or can I do something to improve this?
SwiftUI
RSS for tagProvide views, controls, and layout structures for declaring your app's user interface using SwiftUI.
Post
Replies
Boosts
Views
Activity
The interactiveDismissDisabled() function in SwiftUI's Sheet no longer works as expected in iOS 18.1 (22B83). It was working as expected until iOS 18.0.1.
Are there any other users experiencing the same issue?
struct ContentView: View {
@State private var openSheet = false
var body: some View {
NavigationStack {
Button("Open") {
openSheet = true
}
.sheet(isPresented: $openSheet) {
SheetView()
}
}
}
}
struct SheetView: View {
@Environment(\.dismiss) private var dismiss
var body: some View {
NavigationStack {
Text("This is the Sheet")
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button("Cancel") { dismiss() }
}
}
.interactiveDismissDisabled()
}
}
}
Supplementary information: In iOS 18.1, even Apple's native Journal app allows users to swipe-to-dismiss the sheet when creating a new entry. Previously, a confirmation dialog would be displayed, but this is no longer the case.
The interactiveDismissDisabled() function in SwiftUI's Sheet no longer works as expected in iOS 18.1 (22B83). It was working as expected until iOS 18.0.1. Are there any other users experiencing the same issue?
struct ContentView: View {
@State private var openSheet = false
var body: some View {
NavigationStack {
Button("Open") {
openSheet = true
}
.sheet(isPresented: $openSheet) {
SheetView()
}
}
}
}
struct SheetView: View {
@Environment(\.dismiss) private var dismiss
var body: some View {
NavigationStack {
Text("This is the Sheet")
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button("Cancel") { dismiss() }
}
}
.interactiveDismissDisabled()
}
}
}
Supplementary information: In iOS 18.1, even Apple's native Journal app allows users to swipe-to-dismiss the sheet when creating a new entry. Previously, a confirmation dialog would be displayed, but this is no longer the case.
Hi all,
Is this allowed:
environment(\.container, MyContainer() as Any)
While injecting Model container into the environment we use Type . Is there any universal injection type that can inject container as set of any types rather than array similar to navigationPath() type-eraser ?
I need a magnifying glass function for one of my SwiftUI Views, but can't find a way to implement it as needed.
I found a Youtube video where the author renders the view twice, overlaying the second over the first, then scaling and masking it to create the illusion of magnification, but this is expensive and doesn't work in many cases where more complex views are presented (e.g. a LazyVGrid).
I've also explored continually capturing partial screenshots and scaling them up to create the illusion of magnification, but there's no straightforward way to achieve this with SwiftUI without getting into the messiness of UIViewRepresentables.
Any help would be greatly appreciated
I have an app with looks at the @Environment(\.horizontalSizeClass) variable and it's mate vertical. On the iPhone 16 sim, if I'm in portrait orientation, It says my vertical class is .regular and horizontal is .compact.
If I rotate to landscape, it says vertical is now compact, and horizontal is still compact. That seems inconsistent.
I'm trying to wrap my head around designing for size class, how am I supposed to think about this?
What I want is two areas of the screen: The main area, which shows a graphic, and a much smaller control and data area, which has a button or two and a very narrow text display, which in my current app counts from 1 to 4. The button area
These areas ought never move from where they are, but their contents ought to rotate in place to reflect the orientation. If portrait, the button area is on the bottom, if landscapeLeft, the button are is to the right, if landscapeRight, the button area is to the left.
This currently sort of works if I test for the max of height or width from a Geometry Reader, but it doesn't handle landscapeRight or portraitUpsideDown correctly.
Text("Sample Text with wrong font type")
.font(.bold)
I know this code is incorrect, and it returns an error stating that .font doesn’t have a .bold type.
However, when I place this incorrect code within a stack…
…no error message appears. Instead, I get:
The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions
when trying to run the code. It’s unclear why the compiler doesn’t specify that the issue originates from .font(.bold). This was confusing, and I spent 20 minutes figuring out it was a typo.
I use defaultScrollAnchor(_ anchor: UnitPoint?) -> some View but I don't know how to animate it?
A view with an onTapGesture is conflicting with a view that is higher in the z- order that also has an onTapGesture. The view higher in the z-order is not consistently getting hits when being tapped from within a List
I tested the life cycle of TabView and its sub-Views through the demo and found something strange. Please help analyze it. Thank you.
The demo project is here https://feedbackassistant.apple.com/feedback/15629780
Operation steps:
Step 1: launch app
Step 2: click Login button
the below log is correct
SettingsViewModel init
HomeViewModel init
HomeView appear
Step 3: click Settings tab
SettingsView appear (correct)
Step 4: click Refresh TabView button the below log is incorrect
Refresh TabView
StatusViewModel init
AccountViewModel init
StatusViewModel init (weird)
AccountViewModel init (weird)
HomeView appear (weird)
StatusViewModel deinit
AccountViewModel deinit
AccountView appear
SettingsViewModel deinit
HomeViewModel deinit
Expect log:
Refresh TabView
SettingsViewModel deinit
HomeViewModel deinit
StatusViewModel init
AccountViewModel init
AccountView appear
My iOS (iPhone/iPad/Mac Catalyst) app has a relatively complex authentication flow, primarily required due to it being an API client. Several of my views have .task modifiers that begin executing code when the views are created.
After moving to iOS 18 and Xcode 16, when running in the Simulator, I began noticing my workflow was breaking as views were being created out of sequence... but not by me 🤯
Here is an example stack when I place a breakpoint inside of this view's .task.
From my logging (and this stack) I can verify I am not creating this view.
This view has no preview associated with it, and there are no previews up the view hierarchy from it either.
This happens in the Simulator only
The only clue I have to go on is this line of text which is present at the top of what looks like ASM when I click on the (5) line in the stack above.
SwiftUI`(1) await resume partial function for dispatch thunk of static SwiftUI.PreviewModifier.makeSharedContext() async throws -> τ_0_0.Context:
If this (or any hierarchical view) used Previews, I'd remove them to see if it had an effect, but they don't! I'm at a loss on what to do here...
I want to use ShareLink+FileRepresentation to save a small text file to my iPhone with the steps below.
Tap [Share...] to display the share sheet. This sheet contains [Save to Files].
Tap [Save to Files].
A black sheet is displayed, but it disappears instantly.
In step 3, I was expecting a browser to be displayed to select the location where the file will be saved. But in fact, a black sheet appears, which quickly disappears.
The implemented code is as follows.
import SwiftUI
@main
struct SLSandboxApp: App {
var body: some Scene {
WindowGroup {
let title = Text("File Output")
let numListString = "123,456,789"
let numListFileName = "numlist.csv"
let tagListFile = TextFile(content: numListString,
filename: numListFileName)
ShareView(title: title,
fileToShare: tagListFile,
messageToPreview: numListFileName)
}
}
}
struct ShareView: View {
let title: Text
let fileToShare: TextFile
let messageToPreview: String
var body: some View {
ShareLink(item: self.fileToShare, preview: SharePreview(self.messageToPreview))
}
}
struct TextFile: Transferable {
let content: String
let filename: String
static var transferRepresentation: some TransferRepresentation {
FileRepresentation(exportedContentType: .data) {
textFile in
let data = textFile.content.data(using: .utf8) ?? Data()
let tempDirectory = FileManager.default.temporaryDirectory
let fileURL = tempDirectory.appendingPathComponent(textFile.filename)
try data.write(to: fileURL)
return SentTransferredFile(fileURL)
}
}
}
The development environment is as follows.
Xcode 15.4 (Deployment Target = iOS Deployment Target 17.5)
macOS 14.6.1
The execution environment is as follows.
iPhone SE Gen3 17.7
The following is a console log from the time the application was launched to the time when the share sheet was displayed by tapping [Share...].
Error acquiring assertion: <Error Domain=RBSServiceErrorDomain Code=1 "(originator doesn't have entitlement com.apple.runningboard.primitiveattribute AND originator doesn't have entitlement com.apple.runningboard.assertions.frontboard AND target is not running or doesn't have entitlement com.apple.runningboard.trustedtarget AND Target not hosted by originator)" UserInfo={NSLocalizedFailureReason=(originator doesn't have entitlement com.apple.runningboard.primitiveattribute AND originator doesn't have entitlement com.apple.runningboard.assertions.frontboard AND target is not running or doesn't have entitlement com.apple.runningboard.trustedtarget AND Target not hosted by originator)}>
(501) personaAttributesForPersonaType for type:0 failed with error Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.mobile.usermanagerd.xpc was invalidated: failed at lookup with error 159 - Sandbox restriction." UserInfo={NSDebugDescription=The connection to service named com.apple.mobile.usermanagerd.xpc was invalidated: failed at lookup with error 159 - Sandbox restriction.}
Received port for identifier response: <(null)> with error:Error Domain=RBSServiceErrorDomain Code=1 "Client not entitled" UserInfo={RBSEntitlement=com.apple.runningboard.process-state, NSLocalizedFailureReason=Client not entitled, RBSPermanent=false}
elapsedCPUTimeForFrontBoard couldn't generate a task port
Received port for identifier response: <(null)> with error:Error Domain=RBSServiceErrorDomain Code=1 "Client not entitled" UserInfo={RBSEntitlement=com.apple.runningboard.process-state, NSLocalizedFailureReason=Client not entitled, RBSPermanent=false}
elapsedCPUTimeForFrontBoard couldn't generate a task port
Received port for identifier response: <(null)> with error:Error Domain=RBSServiceErrorDomain Code=1 "Client not entitled" UserInfo={RBSEntitlement=com.apple.runningboard.process-state, NSLocalizedFailureReason=Client not entitled, RBSPermanent=false}
elapsedCPUTimeForFrontBoard couldn't generate a task port
The following is the console log that was written when I tapped [Save to file] on the share sheet.
cancelled request - error: The operation couldn’t be completed. Invalid argument
What modifications should I make to the code to get the expected result?
I've encountered a weird issue with the new Map for iOS 17. In my list, which includes a MapView among other elements, I've observed that with the new initializer, the top and bottom bars are persistently displayed. They don't hide and only appear when scrolling, as they should. This problem doesn't occur with the old, now-deprecated initializer. To illustrate this, I have two screenshots: one with the map enabled and the other with the map disabled, demonstrating the issue.
Here is also my new Map code:
struct MapListRowView: View {
@Binding internal var location: LocationModel
@State internal var user: Bool = true
private var position: CLLocationCoordinate2D { .init(latitude: location.latitude, longitude: location.longitude) }
private var isPad: Bool { UIDevice.current.userInterfaceIdiom == .pad ? true : false }
var body: some View {
Map(bounds: .init(minimumDistance: 1250)) {
if user { UserAnnotation() }
Annotation("", coordinate: position) {
ZStack {
Circle().fill().foregroundColor(.white).padding(1)
Image(systemName: "mappin.circle.fill")
.resizable()
.foregroundColor(.indigo)
}.frame(width: 20, height: 20).opacity(user ? .zero : 1.0)
}
}
.frame(height: isPad ? 200 : 100)
.cornerRadius(8)
.listRowInsets(.init(top: -5, leading: .zero, bottom: -5, trailing: .zero))
.padding(.vertical, 5)
.disabled(true)
}
}
In one of my applications I use several List views with Sections. After upgrading to Sequoia I faced the issue, that after selecting an item, the List suddenly scrolls to a different position. Sometimes the selection even gets out of the view, but in every case a double click just went to the wrong item.
At one list I found out, that the issue could be solved after changing the data source. I used a computed property, what seems to be a stupid idea. After changing this it now works.
Unfortunately there is another List, where this didn't bring the solution. And unfortunately, I cannot reproduce the issue in a code example. One guess of mine is, that it could be related to the fact, that the rows have different heights (because in some are two lines of text and in some are three). And it seems to happen only in very long lists.
It worked perfectly in Sonoma.
Does anyone face the same issue?
Hi,
In the visionOS documentation
Positioning and sizing windows - Specify initial window position
In visionOS, the system places new windows directly in front of people, where they happen to be gazing at the moment the window opens.
Positioning and sizing windows - Specify window resizability
In visionOS, the system enforces a standard minimum and maximum size for all windows, regardless of the content they contain.
The first thing I don't understand is why it talk about macOS in visionOS documentation.
The second thing, what is this page for if it's just to tell us that on visionOS we have no control over the position and size of 2D windows. Whereas it is precisely the opposite that would be interesting. I don't understand this limitation. It limits so much the use of 2D windows under visionOS.
I really hope that this limitation will disappear in future betas.
Is there a way to structure three views vertically with a top, middle divider, and bottom view, where the…
Middle divider view “hugs” its contents vertically (grows and shrinks based on height of child views)
Top and bottom views fill the space available above and below the divider
Divider can be dragged all the way up (or down), to completely hide the top view (or bottom view)
I’ve been working on this for a while and still can’t get it quite right. The code below is close, but the parent view’s bottom edge shifts when the divider resizes. As a result, the bottom view shifts upward when the divider shrinks, whereas I want it to continue to fill the space to the bottom of the screen.
import SwiftUI
struct ContentView: View {
@State private var topRatio: CGFloat = 0.5
@State private var dividerHeight: CGFloat = 44
var body: some View {
GeometryReader { geometry in
let topInset = geometry.safeAreaInsets.top
let bottomInset = geometry.safeAreaInsets.bottom
let totalHeight = geometry.size.height
let availableHeight = max(totalHeight - bottomInset - dividerHeight, 0)
VStack(spacing: 0) {
TopView()
.frame(height: max(availableHeight * topRatio - topInset, 0))
.frame(maxWidth: .infinity)
.background(Color.red.opacity(0.3))
DividerView()
.background(GeometryReader { proxy in
Color.clear.preference(key: DividerHeightKey.self, value: proxy.size.height)
})
.onPreferenceChange(DividerHeightKey.self) { height in
dividerHeight = height
}
.gesture(
DragGesture()
.onChanged { value in
let maxDragDistance = availableHeight + dividerHeight
let translation = value.translation.height / max(maxDragDistance, 1)
let newTopRatio = topRatio + translation
topRatio = min(max(newTopRatio, 0), 1)
}
)
.zIndex(1)
BottomView()
.frame(height: max(availableHeight * (1 - topRatio), 0))
.frame(maxWidth: .infinity)
.background(Color.green.opacity(0.3))
}
}
}
}
struct DividerHeightKey: PreferenceKey {
static var defaultValue: CGFloat = 44
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
value = nextValue()
}
}
struct DividerView: View {
@State private var showExtraText = true
var body: some View {
VStack(spacing: 0) {
Text(showExtraText ? "Tap to hide 'More'" : "Tap to show 'More'")
.frame(height: 44)
if showExtraText {
Text("More")
.frame(height: 44)
}
}
.frame(maxWidth: .infinity)
.background(Color.gray)
.onTapGesture {
showExtraText.toggle()
}
}
}
struct TopView: View {
var body: some View {
VStack {
Spacer()
Text("Top")
}
.padding(0)
}
}
struct BottomView: View {
var body: some View {
VStack {
Text("Bottom")
Spacer()
}
.padding(0)
}
}
#Preview {
ContentView()
}
Before I waste time creating an Apple Developer Support ticket, I’m hoping an Apple DTS engineer can confirm if this is just log noise.
Here’s the code:
import SwiftUI
struct ContentView: View {
@State private var editMode: EditMode = .inactive
@State private var items = ["Item 1", "Item 2", "Item 3"]
var body: some View {
NavigationStack {
List {
ForEach(items, id: \.self) { item in
Text(item)
}
.onDelete { indexSet in
items.remove(atOffsets: indexSet)
}
}
.environment(\.editMode, $editMode)
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
EditButton()
.environment(\.editMode, $editMode)
}
}
}
}
}
#Preview {
ContentView()
}
When you run this code and tap Edit, you’ll initially get:
CoreSVG has logged an error. Set environment variabe [sic] "CORESVG_VERBOSE" to learn more.
After setting CORESVG_VERBOSE = YES, you’ll see:
CoreSVG: Error: NULL ref passed to getObjectCoreSVG: Error: NULL ref passed to getObject
This error only appears the first time Edit is tapped after a build and run. It won't happen again, even after force-quitting and reopening the app. The issue also only happens on iOS 18.0 and 18.1—I can’t reproduce it on iOS 17.5. Fortunately, it doesn’t seem to cause any negative side effects.
Is this just log noise?
I'm trying to use a SwiftUI view as UICalendarView decoration and I get Call to main actor-isolated instance method 'makeContentView()' in a synchronous nonisolated context; this is an error in the Swift 6 language mode in the following code:
class Coordinator: NSObject, UICalendarViewDelegate {
func calendarView(_ calendarView: UICalendarView, decorationFor dateComponents: DateComponents) -> UICalendarView.Decoration? {
.customView {
UIHostingConfiguration {
...
}
.makeContentView()
}
}
}
I've fixed using MainActor.assumeIsolated but is this the correct approach or is there a better one?
class Coordinator: NSObject, UICalendarViewDelegate {
func calendarView(_ calendarView: UICalendarView, decorationFor dateComponents: DateComponents) -> UICalendarView.Decoration? {
.customView {
MainActor.assumeIsolated {
UIHostingConfiguration {
...
}
.makeContentView()
}
}
}
}
Don’t over-engineering! No suggested architecture for SwiftUI, just MVC without the C.
On SwiftUI you get extra (or wrong) work and complexity for no benefits. Don’t fight the system.
I'm using Xcode 14.1 to start a Core Data project. I created a new Project, checking CoreData. The resulting program works in Preview and in the Simulator.
I've changed the data from a Item/timestamp to Locations/title. I plan to add more Attributes but that's for later.
I think I've got all the Item instances changed to Locations and timestamp to title. It seems to work OK when in Preview for ContentView.swift but crashes in the Simulator with the error
Swift/UnsafeRawBufferPointer.swift:946: Fatal error: UnsafeRawBufferPointer with negative count
Any suggestions on what I have done wrong? Thanks.
PS, the New Project includes the line Text("Select a location") but Select a location doesn't appear in the Preview.