如何在小部件预览SwiftUI iOS 14中加载WKWebView

问题描述

如何在swiftui ios 14中加载wkwebview swiftui的新功能以及我很好奇苹果是否允许使用此东西?

import WidgetKit
import SwiftUI
import WebKit
import Photos

struct Provider: TimelineProvider {
    func placeholder(in context: Context) -> SimpleEntry {
        SimpleEntry(date: Date())
    }

    func getSnapshot(in context: Context,completion: @escaping (SimpleEntry) -> ()) {
        let entry = SimpleEntry(date: Date())
        completion(entry)
    }

    func getTimeline(in context: Context,completion: @escaping (Timeline<Entry>) -> ()) {
        var entries: [SimpleEntry] = []

        let currentDate = Date()
        for hourOffset in 0 ..< 5 {
            let entryDate = Calendar.current.date(byAdding: .hour,value: hourOffset,to: currentDate)!
            let entry = SimpleEntry(date: entryDate)
            entries.append(entry)
        }

        let timeline = Timeline(entries: entries,policy: .atEnd)
        completion(timeline)
    }
}

struct SimpleEntry: TimelineEntry {
    let date: Date
}

struct WebWidgetEntryView : View {
    var entry: Provider.Entry
     var body: some View {
        WebView(request: URLRequest(url: URL(string: "https://www.apple.com")!))
    }      
}

@main
struct WebWidget: Widget {
    let kind: String = "WebWidget"

    var body: some WidgetConfiguration {
        StaticConfiguration(kind: kind,provider: Provider()) { entry in
            WebWidgetEntryView(entry: entry)
        }
        .configurationdisplayName("My Widget")
        .description("This is an example widget.")
    }
}

struct WebWidget_Previews: PreviewProvider {    
    static var previews: some View {
        WebView(request: URLRequest(url: URL(string: "https://www.apple.com")!))
    }

}
    
struct ActivityIndicator: UIViewRepresentable {

    @Binding var isAnimating: Bool
    let style: UIActivityIndicatorView.Style

    func makeUIView(context: UIViewRepresentableContext<ActivityIndicator>) -> UIActivityIndicatorView {
        return UIActivityIndicatorView(style: style)
    }

    func updateUIView(_ uiView: UIActivityIndicatorView,context: UIViewRepresentableContext<ActivityIndicator>) {
        isAnimating ? uiView.startAnimating() : uiView.stopAnimating()
    }
}

struct LoadingView<Content>: View where Content: View {

    @Binding var isShowing: Bool
    var content: () -> Content

    var body: some View {
        GeometryReader { geometry in
            ZStack(alignment: .center) {

                self.content()
                    .disabled(self.isShowing)
                    .blur(radius: self.isShowing ? 3 : 0)

                vstack {
                    Text("Loading...")
                    ActivityIndicator(isAnimating: .constant(true),style: .large)
                }
                .frame(width: geometry.size.width / 2,height: geometry.size.height / 5)
                .background(Color.secondary.colorInvert())
                .foregroundColor(Color.primary)
                .cornerRadius(20)
                .opacity(self.isShowing ? 1 : 0)

            }
        }
    }

}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        WebView(request: URLRequest(url: URL(string: "https://www.apple.com")!))
    }
}
struct WebView : UIViewRepresentable {
    
    let request: URLRequest
    
    func makeUIView(context: Context) -> WKWebView  {
        return WKWebView()
    }
    
    func updateUIView(_ uiView: WKWebView,context: Context) {
        uiView.load(request)
    }
    
}

解决方法

不幸的是,您可以在小部件中使用的视图存在一些限制。

由于窗口小部件视图不允许交互(Link除外),因此您不允许在窗口小部件中使用ScrollView。而且我怀疑WKWebView是建立在UIScrollView之上的。

如果要显示一些URL内容,则有两个选择:

  • 在TimelineProvider中获取数据并传递给Entry
  • 按照this answer的建议使用Data(contentsOf: url)
,

这是我以某种方式设法解决的解决方案

https://github.com/Farazahmed90/WebView-Widget-iOS14