简体   繁体   English

当通过 macOS 本机应用程序内的 SwiftUI WKWebView 调用时,如何让文件打开对话框工作?

[英]How do I get the file open dialog to work, when called through a SwiftUI WKWebView inside a macOS native app?

I'm currently running a simplistic WkWebView made in SwiftUI - with all the advice that I was able to glimpse from this StackOverflow post .我目前正在运行一个用 SwiftUI 制作的简单 WkWebView - 包含我能够从这篇 StackOverflow 帖子中看到的所有建议。 It opens up a website.它打开一个网站。 The website has a browser button.该网站有一个浏览器按钮。 If I click on the browser button on Safari, a Finder window opens.如果我单击 Safari 上的浏览​​器按钮,则会打开一个 Finder 窗口。 If I do the same thing inside the .app created with Xcode, a Finder window does not open.如果我在用 Xcode 创建的 .app 中做同样的事情,Finder 窗口不会打开。

This is the stuff I've enabled in the Sandbox:这是我在沙箱中启用的东西:

XCode 应用沙盒设置

The code that I use is this (all from ContentView.swift)我使用的代码是这个(全部来自 ContentView.swift)

import SwiftUI
import WebKit


public struct WebBrowserView {

    private let webView: WKWebView = WKWebView()

    // ...

    public func load(url: URL) {
        webView.load(URLRequest(url: url))
    }

    public class Coordinator: NSObject, WKNavigationDelegate, WKUIDelegate {

        var parent: WebBrowserView

        init(parent: WebBrowserView) {
            self.parent = parent
        }

        public func webView(_: WKWebView, didFail: WKNavigation!, withError: Error) {
            // ...
        }

        public func webView(_: WKWebView, didFailProvisionalNavigation: WKNavigation!, withError: Error) {
            // ...
        }

        public func webView(_: WKWebView, didFinish: WKNavigation!) {
            // ...
        }

        public func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
            // ...
        }

        public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
            decisionHandler(.allow)
        }

        public func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
            if navigationAction.targetFrame == nil {
                webView.load(navigationAction.request)
            }
            return nil
        }
    }

    public func makeCoordinator() -> Coordinator {
        Coordinator(parent: self)
    }
}


#if os(macOS) // macOS Implementation (iOS version omitted for brevity)
extension WebBrowserView: NSViewRepresentable {

    public typealias NSViewType = WKWebView

    public func makeNSView(context: NSViewRepresentableContext<WebBrowserView>) -> WKWebView {

        webView.navigationDelegate = context.coordinator
        webView.uiDelegate = context.coordinator
        return webView
    }

    public func updateNSView(_ nsView: WKWebView, context: NSViewRepresentableContext<WebBrowserView>) {

    }
}
#endif

struct BrowserView: View {

    private let browser = WebBrowserView()

    var body: some View {
        HStack {
            browser
                .onAppear() {
                    self.browser.load(url: URL(string: "http://specificwebsitewithbrowserbutton")!)
                }
        }
        .padding()
    }
}


struct ContentView: View {

    @State private var selection = 1

    var body: some View {
                BrowserView()
                .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}

So, how do I give this .app enough permissions so that a Finder window will open when I click a "Upload" button on the website?那么,如何给这个 .app 足够的权限,以便在我点击网站上的“上传”按钮时打开 Finder 窗口?

You have to implement the following WKUIDelegate delegate method您必须实现以下WKUIDelegate委托方法

   /** @abstract Displays a file upload panel.
     @param webView The web view invoking the delegate method.
     @param parameters Parameters describing the file upload control.
     @param frame Information about the frame whose file upload control initiated this call.
     @param completionHandler The completion handler to call after open panel has been dismissed. Pass the selected URLs if the user chose OK, otherwise nil.

     If you do not implement this method, the web view will behave as if the user selected the Cancel button.
     */
    @available(OSX 10.12, *)
    optional func webView(_ webView: WKWebView, runOpenPanelWith 
                  parameters: WKOpenPanelParameters, initiatedByFrame frame: WKFrameInfo, 
                  completionHandler: @escaping ([URL]?) -> Void)

Here is example of implementation下面是示例实现的

func webView(_ webView: WKWebView, runOpenPanelWith parameters: WKOpenPanelParameters, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping ([URL]?) -> Void) {
    let openPanel = NSOpenPanel()
    openPanel.canChooseFiles = true
    openPanel.begin { (result) in
        if result == NSApplication.ModalResponse.OK {
            if let url = openPanel.url {
                completionHandler([url])
            }
        } else if result == NSApplication.ModalResponse.cancel {
            completionHandler(nil)
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何为 MacOS 创建 WKWebView 应用程序 - How do I create a WKWebView App for MacOS 如何判断最前面的 window 是否是使用 Applescript 在 MacOS 中的 NSOpenPanel / 文件打开对话框? - How do I tell if the frontmost window is a NSOpenPanel / file open dialog in MacOS using Applescript? 如何使用 SwiftUI 向 macOS 应用程序添加工具栏? - How do I add a toolbar to a macOS app using SwiftUI? 如何在 SwiftUI macOS App 中限制 window 实例? - How do I limit window instance in a SwiftUI macOS App? SwiftUI:在 macOS 上使用 HStack 内的 3 个 TextField 调整 ScrollView 的大小时,应用程序崩溃 - SwiftUI: App crashes when resizing ScrollView with 3 TextField inside HStack on macOS 如何在 macOS SwiftUI 应用程序中以编程方式打开设置 window - How to programatically open Settings window in a macOS SwiftUI App 如何在 macOS 上从 SwiftUI 按钮打开 2 个窗口组? - How do you open 2 windowgroups from SwiftUI button on macOS? 如何在 macOS 上从 WKWebview 内部下载文件 - How to download files from inside WKWebview on macOS 如何将 SwiftUI 连接到基于 macOS 文档的应用程序中的文档? - How do I connect SwiftUI to a Document in a macOS Document-based app? 如何在 SwiftUI 中以编程方式为 macOS 应用程序设置或禁用主菜单键盘快捷方式? - How do I set or disable main menu keyboard shortcut programmatically in SwiftUI for a macOS app?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM