I am surprised at what I am seeing with the new @Observable framework in iOS 17.
It seems that if the view containing the @State var, ie viewModel, is modified, then the init of that viewModel will also be called. This is not the behavior of the prior StateObject method of using a viewModel.
As I understand the @State should not be reinitialized on redrawing on the View, is this the expected behavior?
Example:
struct ContentView: View {
@State var offset = false
var body: some View {
VStack {
InnerView()
.offset(x: offset ? 200 : 0)
Button("Offset") {
offset.toggle()
}
}
}
}
// iOS 17 Observable method:
struct InnerView: View {
@State var viewModel: ViewModel
init() {
self._viewModel = State(wrappedValue: ViewModel())
}
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Hello, world!")
}
.padding()
}
}
@Observable
class ViewModel {
init() {
print("ViewModel Init")
}
}
// StateObject method:
struct InnerView: View {
@StateObject var viewModel: ViewModel
init() {
self._viewModel = StateObject(wrappedValue: ViewModel())
}
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Hello, world!")
}
.padding()
}
}
class ViewModel: ObservableObject {
init() {
print("ViewModel Init")
}
}
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hello, I have a Task model in my application which has an optional many to many relationship to a User model.
task.assignedUsers
user.tasks
I am looking to construct a SwiftData predicate to fetch tasks which either have no assigned users or assigned users does not contain specific user.
Here is a partially working predicate I have now:
static func assignedToOthersPredicate() -> Predicate<Task> {
let currentUserGUID = User.currentUserGUID
return #Predicate<Task> { task in
task.assignedUsers.flatMap { users in
users.contains(where: { $0.guid != currentUserGUID })
} == true
}
}
This only returns tasks assigned to others, but not those which have no assigned users.
If combine it with this:
static func notAssignedPredicate() -> Predicate<Task> {
return #Predicate<Task> { task in
task.assignedUsers == nil
}
}
Then I get a run time crash: "to-many key not allowed here"
What is the proper way to do this?
Thanks.
If use a SortDescriptor for a model and sort by some attribute from a relationship, in DEBUG mode it all works fine and sorts. However, in release mode, it is an instant crash.
SortDescriptor(.name, order: .reverse) ---- works
SortDescriptor(.assignedUser?.name, order: .reverse) ---- works in debug but crash in release.
What is the issue here, is it that SwiftData just incompetent to do this?