Post

Replies

Boosts

Views

Activity

Reply to onGeometryChange: Assertion failed: Block was expected to execute on queue
Same thing happens to me. Useless stack trace, with EXC_BREAKPOINT in SwiftUI.AsyncRenderer. What's even worse is that settings the value isn't even an requirement for the crash. VStack(spacing: 0) { // ... } .onGeometryChange(for: CGRect.self) { proxy in proxy.frame(in: .local) } action: { frame in /* do nothing */ } This crashes too. The mere presence of the onGeometryChange modifier causes a seemingly unavoidable crash. Even more curiously, this always happen at this exact location, but if I render the same view in another part of my app it works perfectly.
Nov ’24
Reply to iOS 18 SwiftData ModelContext reset
I believe I now know exactly what's causing this. I've filed FB14344675 with a detailed description of the problem. When an @ModelActor is created and later released (for example dropped at the end of a function scope), the model instances fetched by its associated model context can't be meaningfully used anymore. This behavior is new in iOS 18. I don't know whether iOS 18 now actually resets the background context on deinit, whether iOS 17 somehow kept it alive until all instances were gone, or whether it's something entirely different that caused this regression. Anyway, the solution is as follows: Do NOT fetch model instances using a ModelActor-conforming actor, if the actor doesn't outlive the fetched instances. Instead, keep the actor around. I'm doing this using a @State variable, but I suppose it could also be done by making the actor a singleton. In the case that the crash is actually indented behavior and model instances aren't supposed to outlive their model context, I'd be very interested in hearing about a proper architectural solution to this problem. The singleton solution seems the simplest, but it makes two assumptions that I don't like at all: The model context has to be well-known and static. In my case, this simply doesn't work, because I have two model containers: One for previews with in-memory storage only, and one for development with proper on-disk storage. Since the "correct" model container is only known at runtime, my actor can't be a singleton. It has to be instantiated with a reference to the model context. This, however, causes the following problem: The actor can't be created on view creation, because the model container isn't (yet) accessible. I don't see a good solution to this. This has been my solution so far: struct MyView: View { @Environment(\.modelContainer) private var container @State private var myActor: MyModelActor? // Use this whenever you need the actor func getModelActor() -> MyModelActor { guard let myActor else { let myActor = MyModelActor(modelContainer: container) self.myActor = myActor return myActor } return myActor } var body: some View { SomeContent() } } That's a super ugly solution in my opinion, and although it does work, I really wouldn't wanna use this if there's a better way.
Jul ’24