SwiftUI:WKWebView 在 macOS 上截断页面内容 (NSViewRepresentable)

The*_*eil 11 macos wkwebview swiftui

我有 , 的基本NSViewRepresentable实现WKWebView,用于 macOS 上的 SwiftUI 应用程序。该UIViewRepresentable等效优良工程在iOS上,但在MacOS(本地,而不是催化剂),上面的内容总是切断。

丢失的数量总是等于父视图(例如选项卡视图)及其填充的大小,这表明 web 视图不断将其内容缩放到窗口大小,而不是视图大小。

例如,这个页面:

切断网页内容

...应如下(如 Chrome 所示)。整个导航栏已被裁剪(尽管两侧似乎不受影响)。

Chrome 版本渲染正确

对于如何解决这个问题,有任何的建议吗?有趣的是,如果我在选项卡之间来回切换,内容会正确显示约 1 秒,然后调整内容大小使其再次被切断。这让我觉得updateNSView方法中需要一些东西,但我不确定是什么。

似乎与此处讨论的问题类似,但这是针对基于 IB 的应用程序的,我看不到将其应用于 SwiftUI 的方法。

使用的代码如下。注意:web 视图作为一个属性保留,因此它可以被其他方法引用(例如触发页面加载、刷新、返回等)

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
Run Code Online (Sandbox Code Playgroud)

用法示例:

struct BrowserView: View {

    private let browser = WebBrowserView()

    var body: some View {
        HStack {
            browser
                .onAppear() {
                    self.browser.load(url: URL(string: "https://stackoverflow.com/tags")!)
                }
        }
        .padding()
    }
}

struct ContentView: View {

    @State private var selection = 0

    var body: some View { 
        TabView(selection: $selection){
            Text("Email View")
                .tabItem {
                    Text("Email")
                }
                .tag(0)
            BrowserView()
                .tabItem {
                    Text("Browser")
                }
                .tag(1)
        }
        .padding()
    }
}
Run Code Online (Sandbox Code Playgroud)

Ahm*_*med 11

我在使用 SwiftUI 的 MacOS 应用程序中遇到了与 WKWebView 完全相同的问题。

对我有用的解决方案是使用 GeometryReader 来获取确切的高度,并将 web 视图放在滚动视图中(我相信它与布局优先级计算有关,但还无法触及它的核心) .

这是对我有用的片段,也许它也适用于你

GeometryReader { g in
    ScrollView {
        BrowserView().tabItem {
            Text("Browser")
        }
        .frame(height: g.size.height)
        .tag(1)

    }.frame(height: g.size.height)
}
Run Code Online (Sandbox Code Playgroud)