SwiftUI: WKWebView отключение содержимого страницы в macOS (NSViewRepresentable)

У меня есть базовый NSViewRepresentable реализация WKWebView, для использования с приложениями SwiftUI в macOS. ВUIViewRepresentable эквивалент отлично работает на iOS, но на macOS (изначально не Catalyst) верхний контент всегда обрезается.

Сумма потерял всегда равен размеру видом родительских (например, ввиду вкладки) и их заполнения, что свидетельствует о том, что веб - просмотр сохраняет масштабирование его содержимое в окне размера, а не вид размера.

Например, эта страница:

... должно быть следующим (как показано в Chrome). Вся панель навигации была обрезана (хотя стороны, похоже, не пострадали).

Есть предложения, как это исправить? Интересно, что если я переключаюсь между вкладками, содержимое отображается правильно в течение ~1 секунды, а затем изменяет размер содержимого, чтобы оно снова обрезалось. Это заставляет меня думать, что вupdateNSView метод, но я не уверен что.

Кажется, это проблема, аналогичная обсуждаемой здесь, но это для приложений на основе IB, и я не вижу способа применить ее для SwiftUI.

Используемый код выглядит следующим образом. Примечание. Веб-представление сохраняется как свойство, поэтому на него можно ссылаться другими методами (такими как запуск загрузки страницы, обновление, возврат и т. Д.)

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: "https://stackru.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()
    }
}

3 ответа

Решение

У меня была такая же проблема с WKWebView в приложении MacOS с использованием SwiftUI.

Решение, которое сработало для меня, - использовать GeometryReader для получения точной высоты и поместить веб-представление внутри scrollview (я считаю, что это как-то связано с расчетом приоритета макета, но пока не смог добраться до его сути).

Вот фрагмент того, что сработало для меня, возможно, это сработает и с вами

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

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

webView.edgesIgnoringSafeArea(.all) похоже, обойти эту проблему.

Решение @Ahmed с GeometryReader довольно элегантно, но я нашел более короткий обходной путь.

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

Кажется, что заполнение по умолчанию, равное 0, вызывает эту проблему. Поэтому я просто установил его на -1.

Другие вопросы по тегам