The solution is don't use view model objects! You have to learn the View struct which is designed to hold your view data in a memory efficient hierarchy. It has a lot of magical features like dependency tracking and change detection which you just have to learn to use SwiftUI effectively.
@Observable is for model data it won't work for view data. You might get close to implementing the same behaviour as the View struct but you'll eventually get stuck so it is a complete waste of time.
Correct SwiftUI code would look like this:
struct ModalConfig {
var isPresented = false
var otherVar = ""
mutating func present() {
isPresented = true
otherVar = ""
}
mutating func dismiss() {
isPresented = false
}
}
struct ModalView: View {
@Binding var config: ModalConfig
var body: some View {
ZStack {
Color.yellow
.ignoresSafeArea()
Button("Close") {
config.dismiss()
}
}
}
}
struct ContentView: View {
@State var config = ModalConfig()
var body: some View {
Button("Present sheet modally") {
config.present()
}
.sheet(isPresented: $config.isPresented) {
ModalView(config: $config)
}
}
}
Post
Replies
Boosts
Views
Activity
Same problem here, ModelConfiguration(cloudKitDatabase: .none) still uses CloudKit and the app crashes in my case with:
CloudKit integration requires that all relationships be optional, the following are not: Contact: addresses
Have to disable CloudKit capability to get it to run which is a terrible workaround.
Submitted FB13209319 referencing FB12276416
Xcode Version 15.0 beta 7 (15A5229h) has the same problem.
It's burning my legs!
Same problem here, it happens when I try this in my AppIntent:
@Parameter(title: "Image")
var file: IntentFile
error: Invalid Swift parseable output message (malformed JSON): `1` (in target 'IntentTest2' from project 'IntentTest2')
error: Invalid Swift parseable output message (malformed JSON): `{
"kind": "finished",
` (in target 'IntentTest2' from project 'IntentTest2')
"name": "compile",
"pid": 64892,
"process": {
"real_pid": 64893
},
"exit-status": 0
}
Command SwiftCompile emitted errors but did not return a nonzero exit code to indicate failure
I have the same error "The action “Demo Action” could not run because an internal error occurred." in Xcode 15 beta 5. I resolved it by making a Multiplatform app template instead of a macOS.
Same problem here.
Your use of URLSession and @StateObject likely means you are attempting to do async networking in this object so it shouldn't be @MainActor because you'll want your async funcs to run on background threads not on the main thread.
Also, when switching from @ObservedObject to @Observable you no longer need to use Task { @MainActor in when setting vars (@Published in case of @ObservedObject) with the results of the network calls.
Better to use @AppStorage for that
Better to store your own location type and transform it into a CLLocationCoordinate2D when you need one. If you're using SwiftUI you can use the View hierarchy to transform from your model type to that type, via a computed property called from body. That way it will only be transformed when it has changed.
It is probably a bad idea to try to store a UI type in the model. It would be better to store a model type in the model and then transform it into a UI type using the SwiftUI View hierarchy, i.e. using a computed property called from body that returns a Color struct created from the model type.
You can do an initial query for related objects but as of Xcode 15 beta 1 it won't automatically update so that could be your problem.
Unfortunately it is still terrible syntax for using a predicate with supplied data as it was for @FetchRequest, they really need to switch from property wrappers to view modifiers for fetching so we can pass in parameters that can dynamically change from parent Views and from States in current View.
struct StudentList: View {
var department: Department
@Query
private var students: [Student]
@Environment(\.modelContext)
private var modelContext
init(department: Department) {
self.department = department
let departmentID = department.objectID
let predicate = #Predicate<Student> { student in
student.department?.objectID == departmentID
}
// let query = Query(filter: filter, sort: \.name)
//
let fd = FetchDescriptor<Student>(predicate: predicate, sortBy: [SortDescriptor(\.name)])
let query = Query(fd, animation: .default)
_students = query // nasty to have to implement and init and use underscore syntax to implement this simple feature
}
edit - "I suppose we would call fetch() from onAppear and onChanged" I meant fetch() is called from computed property that is used in a ForEach.
Yes but as of Xcode 15 beta 1 it is very broken. See Build an app with SwiftData and the "build document-based applications backed by SwiftData storage" https://developer.apple.com/wwdc23/10154
Seems it's a known issue:
"@Query results can appear stale or fail to refresh. (108385553)"
https://developer.apple.com/documentation/ios-ipados-release-notes/ios-ipados-17-release-notes
In SwiftUI the View struct is a view model already you don't need your own objects, if you try to then you'll just run into the same kind of bugs that Swift's use of value types like structs was designed to eliminate. SwiftUI diffs these structs and then creates/updates/removes UIView (or NSView) objects automatically on your behalf. So you can think of the View struct as simply view data rather than part of the view layer in the traditional MVC sense. It's worth learning the basics of the View structs features like all the different situations that body is called, e.g. if a let is changed from the last time the View was init, or if a state is set (that has had its getter called). If you previously used MVVM in UIKit (FYI you should have instead learned child view controllers and the responder chain) then you can just forget about MVVM in SwiftUI.
If you paid Stanford University to teach you MVVM in SwiftUI then you should probably ask for a refund because that is one huge mistake.