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.