简体   繁体   中英

macOS SwiftUI dismiss app-modal NSHostingController presented via segue from menu?

I'm working on a macOS SwiftUI app. It has a "File->Open Location…" menu command that uses a Segue in IB to modally present an NSWindowController that contains an NSHostingController subclass. My subclass looks like this:

class
OpenLocationController: NSHostingController<OpenLocationView>
{
    @objc
    required
    dynamic
    init?(coder: NSCoder)
    {
        super.init(coder: coder, rootView: OpenLocationView())
    }
}

and my view looks like this:

struct
OpenLocationView : View
{
    @State private var location: String = ""

    var body: some View
    {
        VStack
        {
            HStack
            {
                Text("Movie Location:")
                TextField("https://", text: $location)
            }

            HStack
            {
                Spacer()
                Button("Cancel") { /* dismiss window */ }
                Button("Open") { }
            }
        }
        .padding()
        .frame(minWidth: 500.0)
    }
}

I tried adding a property @Environment(\\.presentationMode) var presentationMode and calling self.presentationMode.wrappedValue.dismiss() in the button action, but it has no visible effect.

How do I dismiss this window when the user clicks Cancel?

Here is possible approach. Tested with Xcode 11.2 / macOS 15.0.

class
OpenLocationController: NSHostingController<OpenLocationView>
{
    @objc
    required
    dynamic
    init?(coder: NSCoder)
    {
        weak var parent: NSViewController? = nil // avoid reference cycling
        super.init(coder: coder, rootView:
            OpenLocationView(parent: Binding(
                get: { parent },
                set: { parent = $0 })
            )
        )

        parent = self // self usage not allowed till super.init
    }
}

struct
OpenLocationView : View
{
    @Binding var parent: NSViewController?
    @State private var location: String = ""

    var body: some View
    {
        VStack
        {
            HStack
            {
                Text("Movie Location:")
                TextField("https://", text: $location)
            }

            HStack
            {
                Spacer()
                Button("Cancel") {
                    self.parent?.dismiss(nil) // if shown via NSViewController.present
                    // self.parent?.view.window?.performClose(nil) // << alternate
                }
                Button("Open") { }
            }
        }
        .padding()
        .frame(minWidth: 500.0)
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM