SwiftUI: WKWebView Cutting Off Page Content on macOS (NSViewRepresentable)

走远了吗. 提交于 2020-03-02 04:02:36

问题


I have a basic NSViewRepresentable implementation of WKWebView, for use with SwiftUI apps. The UIViewRepresentable equivalent works fine when run on iOS, but when running on macOS (natively, not Catalyst), the top content is always cut off.

The amount lost always equals the size of parent views (such as the tab view) and their padding, which indicates that the web view keeps scaling its content to the window size, rather than the view size.

For example, this page:

...should be as follows (as shown in Chrome). The entire navigation bar has been cropped out (though the sides appear not to be affected).

Any suggestions on how to fix this? Interestingly, if I switch back & forth between tabs, the content shows correctly for ~1 second, then resizes the content so it's cut off again. This makes me think something's required in the updateNSView method, but I'm not sure what.

Seems to be a similar issue to the one discussed here, but that's for IB-based apps, and I can't see a way to apply it for SwiftUI.

The code used is as follows. Note: The web view is kept as a property so it can be referenced by other methods (such as triggering page load, refresh, go back, etc.)

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

Example usage:

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()
    }
}

回答1:


I had the exact same issue with WKWebView in MacOS app using SwiftUI.

The solution that worked for me is to use GeometryReader to get the exact height, and put the web view inside a scrollview (I believe it has something to do with the layout priority calculation, but couldn't get to the core of it yet).

Here is a snippet of what worked for me, maybe it will work with you as well

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

    }.frame(height: g.size.height)
}


来源:https://stackoverflow.com/questions/59347963/swiftui-wkwebview-cutting-off-page-content-on-macos-nsviewrepresentable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!