我需要在多个上下文中运行 WKWebView,包括没有视图的上下文。
在App中就可以了。 加载它、链接它、显示它。 但我还需要将其加载到小部件中 - 不是为了显示,而是为了访问页面上的 indexeddb 中存储的数据,也用于后台处理任务(尽管这不太重要),最后在推送通知的处理程序中。 这里的问题是我不想将我的整个数据存储移动到应用程序中 - 然后我也必须为 Android 复制相同的存储 - 并且它在浏览器中工作正常 - 我不想要 3 个版本,如果我可以避免它。 对于网络应用程序,本地存储和 indexeddb 存储效果很好。 对于 WKWebView,它非常棒,如果我需要信息,我可以从页面请求它。 但是 WKWebView 似乎需要附加到实时视图层次结构,而不能附加到小部件视图层次结构。
有没有人有办法在不附加到视图堆栈的情况下实例化工作 WKWebView,或者在没有完整 WKWebView 的情况下访问站点的 WKWebView 本地存储和/或 indexeddb 存储(例如,访问 JSContext 但将其绑定到一个完整的网站) 注意:我正在尝试构建可以离线运行的代码,所以我不能只查询我的主站点的数据。
作为一个例子(实际上不是我正在构建的,但它传达了这个想法......) 想象一下在线日历服务。 该应用程序显示日历,允许添加新项目等。所有约会都在本地缓存在indexeddb中,因此即使您处于离线状态,您也可以打开该应用程序并查看它们。 现在您想要一个小部件来显示日历。 它需要访问相同的数据。 同样,您在失去信号之前收到新日历项目的通知 - 您打开应用程序希望看到它(毕竟,您的手机已收到它),但它不在那里,因为通知处理程序无法访问网络 - indexeddb 的上下文
我想做的是...
let web = WKWebView(noViewContext)
web.load("https://example.com/functionpage") // note, relying on caching here. I have that sorted)
web.evaluateJavaScript("SomeCodeHere()") { (outcome, error) in etc. etc.}
对于您的情况,尝试在后台 WKProcessPool 中创建 WKWebView,以跨应用程序、小部件和后台任务共享会话和 IndexedDB 数据,而不显示它。这需要使用共享存储设置 WKWebViewConfiguration。
let config = WKWebViewConfiguration()
config.processPool = sharedProcessPool // Instantiate once, reuse for app & widget
let webView = WKWebView(frame: .zero, configuration: config)
webView.load(URLRequest(url: URL(string: "https://example.com/functionpage")!))
webView.evaluateJavaScript("SomeCodeHere()") { result, error in
guard let data = result as? String else {
print("JavaScript evaluation failed: \(error?.localizedDescription ?? "unknown error")")
return
}
print("JavaScript output: \(data)")
}
对于小部件,frame: .zero 使其远离屏幕,但 WKProcessPool 中的缓存数据仍然可以访问。虽然 iOS 并不正式支持不可见的 WKWebView,但这种具有共享 WKProcessPool 的设置应该可以跨上下文访问和缓存 IndexedDB 以满足您的需求,而无需重复存储。