Found the cause and fix, though I don't 100% understand why it's happening. The views in the VStack (PostView in the code above) contained a @SceneStorage property. Removing the @SceneStorage allows the list to scroll quickly, even with .scrollTargetLayout(). No excessive calls to .body.
I'm guessing that as the scrolled views come and go, that the @SceneStorarge var was getting marked as changed, even though it wasn't, causing all other cached views to be invalidated? But how does .scrollTargetLayout cause this?
Anyway, elevating the @SceneStorage to the containing view, and passing into PostView as a binding, fixed scrolling, and still gives access to that @ScensStorage var.
Post
Replies
Boosts
Views
Activity
So sorry, I really misunderstood something. The objects are not being reinitialized. It's just that scrollTargetLayout() with this configuration causes a tremendous amount of re-rendering.
My bad.
Still a problem though. It still makes scrolling unusably slow, even with a small data set.
@RichLogan I see that Xcode 16.2 has been pulled from cloud configs, so Latest Version is 16.1 again. Your Mac builds should work now, as mine are.
Same here. MacOS build only. Quite an inconvenience. We want to love you #xcodecloud, please do better.
Same. Version 16.1 (16B40)
@John-Doe Cloud builds and archiving are working for me now, after some random failures this morning. Hope it's cleared up for you.
I'm also seeing random failures today at the very end of builds, when exporting the archive.
Seems like after yesterday's outage, things aren't quite right yet.
A flip side of @gwachobt's problem... today some configuration changed on Xcode cloud so that Latest Release and Latest Beta or Release is back to 15.4.
Devs with Xcode 16 projects need to select it from the Release Versions section of the Menu, then remember later to set it back to Latest Release when the dust settles.
The documentation, and Quinn's Fight article, imply that an App Store distribution of a native Mac app with an iOS-style app group will work, due to some manual approval by app store reviewers. Can anyone verify that?
@Gil and @max_us I just gave up on SwiftData and reverted to Core Data. A pretty painful few days on a large app, but in the end it runs great on the fall OS's, and I have the convenience of FetchedResultsController for non-view code.
I have a gut feeling this won't be fixed in the fall releases.
@malc Interesting idea. I don't think I'm initing twice. A SwiftData engineer acknowledged the corrupted modelContext environment variable as a known bug.
Container initialized in a singleton...
@MainActor struct DataCenter {
static var shared:DataCenter = DataCenter.init()
public let container: ModelContainer
public let context: ModelContext
init() {
let schema = Schema([
Folder.self,
Reminder.self,
DateReminder.self,
LocationReminder.self
])
container = try! ModelContainer(for: schema, configurations: [ModelConfiguration(isStoredInMemoryOnly: false)])
context = container.mainContext
}
}
Setting the container...
WindowGroup {
ContentView()
}
.modelContainer(DataCenter.shared.container)
I don't reference the modelContext environment variable anywhere. In code that needs the context, I always reference the singleton...
let folder = Folder(name: newFolderName)
DataCenter.shared.context.insert(folder)
It's been working fine, until iOS 18 came along. But I think my many problems with SwiftData in 18 have nothing at all to do with this container usage. But I've been wrong before.
Ziqiao, thanks for the fetchCount workaround. Unfortunately I've found another case. Simply iterating over a @Query with ForEach causes the same problem. No call to count.
Your suggestion to make large items in externalStorage reference instead does help in this case too. But it points to a serious problem in SwiftData, where Query macros become useless in non-trivial apps.
(I'm pretty sure that the problem does not happen when iterating or counting an array representing a one-to-many relationship. Hard to be sure because I can't get the app running well enough to exercise in iOS 18)
I do hope that it's fixable, because this is not how SwiftData is supposed to work, and everything works fine on iOS 17.
This seems a lot like a bug that was introduced to SwiftData around the 17.4 timeframe. The modelContext environment variable becomes corrupted as the app becomes de-active, then when in the background some SwiftData/SwiftUI activity, relying on that variable, crashes.
With autosave turned off, that background activity doesn't happen, but you even when that's turned off you'll probably be bitten eventually.
The solution is to avoid relying on the modelContext environment variable, instead setting the modelContainer manually on a root view.
See these threads for a deeper discussion :
https://developer.apple.com/forums/thread/750084?answerId=52256025#52256025
https://developer.apple.com/forums/thread/744194?answerId=788019022#788019022
@outcoldman Answering you after a few months... sorry, disabling and waiting doesn't fix it. Mine's been broken for nearly a year.
Thanks Ziqiao, for these great ideas!
I've tried both, separately, in my test project....
Replacing the data property with a relationship does indeed avoid loading the images until needed. A good workaround. I'll test it in my real project to see what happens with more complexity and scale.
Using fetchCount on a FetchDesciptor instead of count on SwiftData's Query array also improves things. It does not load the entire dataset to make the count.
So thanks for these workarounds. Used together they may allow a SwiftData app to run normally on iOS 18.
Now just thinking out loud, for myself and for fellow developers facing the same issues, strategizing about iOS 18 (and other fall 2024 os's)....
Changing the image properties to relationships has these costs and risks....
I'll probably have to write a migrator, as this change seems unlikely to be handled automatically by lightweight migration.
Will swift data reliably manage and discard the related items? Any different behavior from being properties?
Changing the queries to FetchDesciptor has these costs and risks....
In my large app, I use the convenience of counting SwiftData's pseudo arrays all over the place. Not just in Queries, but in relationships. How much work will it be to inject FetchDesciptors everywhere? Any performance difference?
Any unforeseen interactions or failures with SwiftUI views?
And the big question, do I just wait a few more Betas and hope that SwiftData's iOS-17-like behavior is restored? Is the old-way I was working closer to SwiftData best practices? When do I give up and make these changes?