If you are using the legacy API, i.e., the ObservableObject protocol, why are you defining the object using the @State property wrapper?
Instead, consider defining an object using the StateObject property wrapper.
I recommend delving into materials on SwiftUI development before publishing questions or code. It will provide you with a better understanding of the concepts.
🙂🙂🙂
Post
Replies
Boosts
Views
Activity
Seems View and its members do not deallocate after a presentation
Modal views usually have a separate hierarchy...
So, I believe this should work:
// Created by Dmitry Novosyolov on 31/10/2023.
//
import SwiftUI
struct ContentView: View {
@State
private var someModalVM: SomeModalViewModel? = nil
var body: some View {
Button("present") {
someModalVM = .init(modalValue: 10)
}
.fullScreenCover(
item: $someModalVM,
onDismiss: {
print("Model Class value: \(someModalVM?.modalValue as Any)")
}
) {
ModalView(someModalVM: $0)
}
}
}
struct ModalView: View {
@Environment(\.dismiss)
private var dismiss
let someModalVM: SomeModalViewModel
var body: some View {
Button("dismiss", action: dismiss.callAsFunction)
.tint(.white)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background {
Color.blue.ignoresSafeArea()
}
}
}
#Preview {
ContentView()
}
@Observable
final class SomeModalViewModel {
let modalValue: Int
init(modalValue: Int) {
self.modalValue = modalValue
print("Model Class value: \(self.modalValue)")
}
}
extension SomeModalViewModel: Identifiable { }
A very basic example - same behavior...
'[SwiftUI] Publishing changes from within view updates is not allowed, this will cause undefined behavior.'
import SwiftUI
//MARK: Content View
struct ContentView: View {
@StateObject
private var someVM: SomeViewModel = .shared
var body: some View {
VStack {
if let value = someVM.bindingValue {
HStack {
Text("value:".capitalized)
Text(value.description)
}
.font(.largeTitle)
}
Button {
someVM.isPresented.toggle()
} label: {
Image(systemName: "exclamationmark.triangle.fill")
.foregroundColor(.orange)
Text("Hello, Beta 5 !")
}
.font(.title2)
.buttonStyle(.bordered)
}
.padding()
.sheet(isPresented: $someVM.isPresented) {
SheetView(someVM: .shared)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
//MARK: Sheet View
struct SheetView: View {
@ObservedObject
var someVM: SomeViewModel
var body: some View {
NavigationStack {
List {
ForEach(0..<10) { value in
Button {
someVM.updateValue(for: value)
} label: {
HStack {
Text("value".capitalized)
Spacer()
Text(value.description)
.bold()
.foregroundColor(.red)
}
}
}
}
.navigationTitle("Sheet View")
}
}
}
//MARK: View Model
final class SomeViewModel: ObservableObject {
static let shared: SomeViewModel = .init()
@Published
private (set) var bindingValue: Int? = nil
@Published
var isPresented: Bool = false
func updateValue(for value: Int) {
Task { @MainActor in
bindingValue = value
isPresented.toggle()
}
}
}
import SwiftUI
struct MailFilterView: View {
@State
private var from = ""
@State
private var to = ""
@Binding
var filter: MailFilter
var body: some View {
NavigationView {
Form {
Section(header: Text("from")) {
TextField("from...", text: $from)
}
Section(header: Text("to")) {
TextField("to...", text: $to)
}
Section(header: Text("save changes")) {
Button(
action: {
filter.criteria.from = from
filter.criteria.to = to
// dismiss the view
}, label: {
Text("Save")
})
.disabled(from.isEmpty || to.isEmpty)
}
}
.onAppear {
from = filter.criteria.from
to = filter.criteria.to
}
}
}
}
struct MailFilter {
var criteria: Criteria
}
struct Criteria {
var from, to: String
}
WWDC21 we are waiting for ...