web-dev-qa-db-ja.com

SwiftUI:モーダル状態のクリアまたは再初期化

状態をクリアまたは再初期化したいSwiftUIモーダルがあります。このモーダルは、いくつかの状態を持つ他のモーダルを開くことができるという事実を考慮して、再初期化することが推奨されます。

以下に簡単な例を示します。

import SwiftUI

struct OtherView: View {
    @State var otherViewState: String = ""

    var body: some View {
        TextField($otherViewState, placeholder: Text("Demo Text Input"))
    }
}

struct Demo: View {
    @State var showModal: Bool = false

    var modal: Modal {
        Modal(OtherView(), onDismiss: { self.showModal = false })
    }

    var body: some View {
        Button(action: { self.showModal = true }) {
            Text("Toggle Modal")
        }
        .presentation(self.showModal ? self.modal : nil)
    }
}

OtherViewがどのように閉じられたかに関係なく、OtherView自体がモーダルを開くことができるという要件で、テキストの状態をクリアした状態で再度開きたいと思います。 OtherView構造体自体にclearメソッドを追加することは常にオプションですが、保守可能な方法であるとは思いません。

以下は、単純化された問題のビデオです: Demo

10
michaelgmcd

9月11日更新:これはiOS 13 GMで修正されたようです。

私は同じことで苦労しており、これは9月までに解決されるバグであると考えたいのですが、フィードバックアシスタントですでに報告しているので、必ず同じことを行ってください!

今のところは、モーダルに表示したいSwiftUIビューをラップする新しいUIHostingControllerを作成するだけです。私はそれが本当にハックに見えることを知っていますが、少なくともそれはうまくいきます:

import SwiftUI

struct OtherView: View {
    @State var otherViewState: String = ""

    var body: some View {
        TextField($otherViewState, placeholder: Text("Demo Text Input"))
    }
}

struct Demo: View {
    var body: some View {
        Button("Toggle Modal") {
            self.showModal()
        }
    }

    func showModal() {
        let window = UIApplication.shared.windows.first
        window?.rootViewController?.present(UIHostingController(rootView: OtherView()), animated: true)
    }
}

特に複数のウィンドウをサポートしている場合は、ウィンドウの取得方法を改善したいと思うかもしれませんが、アイデアは理解できたと思います。

1
GuiyeC

.onAppear()でモーダルを再初期化できます。この例はBeta 3で動作します。

import SwiftUI

struct ModalView : View {

    @Environment(\.isPresented) var isPresented: Binding<Bool>?

    @State var textName: String = ""

    var body: some View {

        NavigationView {

            Form {
                Section() {
                     TextField("Name", text: self.$textName)
                        .textFieldStyle(.roundedBorder)
                }
            }
            .listStyle(.grouped)
                .navigationBarTitle(Text("Add Name"), displayMode: .large)
                .navigationBarItems(leading: Button(action:{ self.dismiss() })
                { Text("Cancel") },
                                    trailing: Button(action:{ self.dismiss() })
                                    { Text("Save") } )
                .onAppear(perform: {
                    self.textName = ""
                })
        }
    }

    func dismiss() {
        self.isPresented?.value = false
    }

}

struct DetailView : View {

    var body: some View {

        PresentationLink(destination: ModalView())
        { Text("Present") }
    }

}

struct ContentView : View {

    var body: some View {

        NavigationView {
            NavigationLink(destination: DetailView())
            { Text("Navigate") }
        }
    }
}
0
Chuck H