SwiftUI WKWebView切断macOS上的页面内容(NSViewRepresentable)

时间:2019-12-15 20:50:57

标签: macos swiftui wkwebview

我有NSViewRepresentable的基本WKWebView实现,可用于SwiftUI应用。当在iOS上运行时,等效的UIViewRepresentable可以正常工作,但是在macOS(本机上不是Catalyst)上运行时,始终会切断顶部内容。

丢失的数量始终等于父视图(例如选项卡视图)及其填充的大小,这表明Web视图将其内容不断缩放为 window 的大小,而不是< em>视图大小。

例如,此页面:

Cut Off Web Content

...应如下所示(如Chrome中所示)。整个导航栏已被裁剪(尽管侧面似乎没有受到影响)。

Chrome Version Rendering Correctly

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

似乎与讨论的here类似,但这是基于IB的应用程序,我看不出将其应用于SwiftUI的方法。

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

public struct WebBrowserView {

    private let webView: WKWebView = WKWebView()

    // ...

    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) // iOS Implementation
extension WebBrowserView: UIViewRepresentable {

    // ...
}

#else // macOS Implementation
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: "https://stackoverflow.com/tags")!)
                }
        }
        .padding()
    }
}

struct ContentView: View {

    @State private var selection = 0

    var body: some View { 
        TabView(selection: $selection){
            EmailView()
                .tabItem {
                    Text("Email")
                }
                .tag(0)
            BrowserView()
                .tabItem {
                    Text("Browser")
                }
                .tag(1)
        }
        .padding()
    }
}

3 个答案:

答案 0 :(得分:6)

在使用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)
}

答案 1 :(得分:0)

@Ahmed 使用 GeometryReader 的解决方案非常优雅,但我找到了一个更短的解决方法。

struct BrowserView: View {
// ...
    var body: some View {
        // ...
        browser.padding(-1.0)
        // ...
    }
}

似乎等于 0 的默认填充会导致此问题。 所以我只是将它设置为 -1。

答案 2 :(得分:-1)

webView.edgesIgnoringSafeArea(.all)似乎可以解决此问题。