SwiftUI使用ObservableObject与Binding会导致弹出表崩溃。

huangapple go评论60阅读模式
英文:

SwiftUI using ObservableObject with Binding cause sheet crash

问题

Root:

class Benef: ObservableObject {
    @Published var val: String = ""
}

@main
struct TestApp: App {
    @StateObject var beenf = Benef()
    var body: some Scene {
        WindowGroup {
            ContentView(testt: $beenf.val)
        }
    }
}

ContentView:

enum Test: Identifiable {
    case one
    case two
    
    var id: String {
        switch self {
        case .one : return "One"
        case .two : return "Two"
        }
    }
}

struct ContentView: View {
    @Environment(\.dismiss) private var dismiss
    @State private var showingFirst: Test?
    @State private var showingSecond: Test?
    @Binding var testt: String

    var body: some View {
        VStack {
            Button("Show First Sheet") {
                showingFirst = .one
            }
        }
        .sheet(item: $showingFirst) { tt in
            FirstSheetiew {
                showingSecond = .two
            }
        }
        .sheet(item: $showingSecond) { tt in
            VStack {
                Text("Second Sheet")
                Button("Dismiss") {
                    dismiss()
                }
            }
        }
    }
}

struct FirstSheetiew: View {
    @Environment(\.dismiss) private var dismiss

    let action: () -> Void

    var body: some View {
        VStack {
            Text("First Sheet")
            Button("Dismiss") {
                action()
                dismiss()
            }
        }
    }
}

Crash error:

"Application tried to present modally a view controller <TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView: 0x12a01b600> that is already being presented by <TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVS_7AnyViewVS_12RootModifier_: 0x12a814e00>."

英文:

I have View with button that display sheet and after first sheet dismiss, I need to display a second sheet, when I use ObservableObject in Binding the View crash after showing the second sheet:

Root:

class Benef: ObservableObject {
    @Published var val: String = &quot;&quot;
}

@main
struct TestApp: App {
    @StateObject var beenf = Benef()
    var body: some Scene {
        WindowGroup {
            ContentView(testt: $beenf.val)
            
        }
    }
}

ContentView:

enum Test: Identifiable {
    case one
    case two
    
    var id: String {
        switch self {
        case .one : return &quot;One&quot;
        case .two : return &quot;Two&quot;
        }
    }
}

struct ContentView: View {
    @Environment(\.dismiss) private var dismiss
    @State private var showingFirst: Test?
    @State private var showingSecond: Test?
    @Binding var testt: String

    var body: some View {
        VStack {
            Button(&quot;Show First Sheet&quot;) {
                showingFirst = .one
            }
        }
        .sheet(item: $showingFirst) { tt in
            FirstSheetiew {
                showingSecond = .two
            }
        }
        .sheet(item: $showingSecond) { tt in
            VStack {
                Text(&quot;Second Sheet&quot;)
                Button(&quot;Dismiss&quot;) {
                    dismiss()
                }
            }
        }
    }
}

struct FirstSheetiew: View {
    @Environment(\.dismiss) private var dismiss

    let action: () -&gt; Void
    
    var body: some View {
        VStack {
            Text(&quot;First Sheet&quot;)
            Button(&quot;Dismiss&quot;) {
                action()
                dismiss()
            }
        }
    }
    
}

Crash error:

"Application tried to present modally a view controller <TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView: 0x12a01b600> that is already being presented by <TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVS_7AnyViewVS_12RootModifier_: 0x12a814e00>."

答案1

得分: 1

这是因为 showingSecond 的值在关闭 FirstSheetView 之前已经被改变。

因此,你需要在 FirstSheetViewonDisappear{ } 中改变 showingSecond 的值。

以下是修复方法:

struct FirstSheetiew: View {
    @Environment(\.dismiss) private var dismiss

    let action: () -&gt; Void
    
    var body: some View {
        VStack {
            Text(&quot;First Sheet&quot;)
            Button(&quot;Dismiss&quot;) {
                //action()  &lt;-- &#128064; 移除
                dismiss()
            }
        }
        .onDisappear {  //&lt;-- &#128064; 添加
            action()
        }
    }
}
英文:

This is because the value of showingSecond was changed before FirstSheetView was closed.

Therefore, you need to change the value of showingSecond inside onDisappear{ } of FirstSheetView.

Here is how to fix it:

struct FirstSheetiew: View {
    @Environment(\.dismiss) private var dismiss

    let action: () -&gt; Void
    
    var body: some View {
        VStack {
            Text(&quot;First Sheet&quot;)
            Button(&quot;Dismiss&quot;) {
                //action()  &lt;-- &#128064; remove
                dismiss()
            }
        }
        .onDisappear {  //&lt;-- &#128064; add
            action()
        }
    }
}

huangapple
  • 本文由 发表于 2023年4月4日 08:10:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/75924584.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定