英文:
MS bookings not working anymore inside WKWebView
问题
我在一个使用SwiftUI的iOS应用中有一个WKWebView,它加载一个Microsoft Bookings网页(我已经测试过多个预订页面,任何公共预订页面都会出现此问题)。这个功能一直正常工作,直到现在,MS Bookings显示一个带有通用错误信息“Something went wrong”的错误页面,并有一个刷新页面的按钮(点击此按钮会出现一个登录页面)。在Android的WebView或者“常规”浏览器中,一切都正常工作。代码如下:
import SwiftUI
import WebKit
struct WebView: UIViewRepresentable {
let request: URLRequest
let options: Options
private var navDelegate: WKNavigationDelegate
private var scrollDelegate: UIScrollViewDelegate
init(
request: URLRequest,
options: Options = Options()
) {
self.request = request
self.options = options
self.navDelegate = WVNavigationDelegate()
self.scrollDelegate = WVUIScrollViewDelegate(scrollEnabled: options.scrollEnabled)
}
func makeUIView(context: Context) -> WKWebView {
let wv = WKWebView()
wv.navigationDelegate = navDelegate
wv.scrollView.delegate = scrollDelegate
// 似乎没有任何区别
if #available(iOS 15.4, *) {
wv.configuration.preferences.isSiteSpecificQuirksModeEnabled = true
}
return wv
}
func updateUIView(_ uiView: WKWebView, context: Context) {
uiView.load(request)
uiView.scrollView.isScrollEnabled = options.scrollEnabled
}
struct Options {
var scrollEnabled: Bool = true
var zoomEnabled: Bool = true
}
}
class WVUIScrollViewDelegate: NSObject, UIScrollViewDelegate {
let scrollEnabled: Bool
init(scrollEnabled: Bool) {
self.scrollEnabled = scrollEnabled
}
func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
scrollView.pinchGestureRecognizer?.isEnabled = scrollEnabled
}
}
class WVNavigationDelegate: NSObject, WKNavigationDelegate {
// 测试检查是否是cookie的问题,但没有任何区别
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
guard let response = navigationResponse.response as? HTTPURLResponse, let url = navigationResponse.response.url else {
decisionHandler(.cancel)
return
}
if let headerFields = response.allHeaderFields as? [String: String] {
let cookies = HTTPCookie.cookies(withResponseHeaderFields: headerFields, for: url)
cookies.forEach { cookie in
webView.configuration.websiteDataStore.httpCookieStore.setCookie(cookie)
HTTPCookieStorage.shared.setCookie(cookie)
}
}
decisionHandler(.allow)
}
}
在WVNavigationDelegate
中,我还注入了一个js脚本到webview中,以拦截需要检测预订是否完成的特定调用,但为了简单起见,我将其省略了,因为即使没有这段代码,问题也会发生。
是否还有其他功能需要配置,比如cookie,因为这些页面在Android的WebView和其他浏览器中都可以工作?
英文:
I have a WKWebView in an iOS app using SwiftUI which loads a Microsft bookings web page (I have tested this with multiple booking pages and it happens with any public booking page). This was working until now, MS bookings now displays an error page with a generic error "Something went wrong" and a button to refresh the page (when clicking on this button a sigin page appears). In a Webview on Android or in a 'regular' browser everything works fine. The code looks like this:
import SwiftUI
import WebKit
struct WebView: UIViewRepresentable {
let request: URLRequest
let options: Options
private var navDelegate: WKNavigationDelegate
private var scrollDelegate: UIScrollViewDelegate
init(
request: URLRequest,
options: Options = Options()
) {
self.request = request
self.content = nil
self.options = options
self.navDelegate = WVNavigationDelegate()
self.scrollDelegate = WVUIScrollViewDelegate(scrollEnabled: options.scrollEnabled)
}
func makeUIView(context: Context) -> WKWebView {
let wv = WKWebView()
wv.navigationDelegate = navDelegate
wv.scrollView.delegate = scrollDelegate
// Seems to make no difference
if #available(iOS 15.4, *) {
wv.configuration.preferences.isSiteSpecificQuirksModeEnabled = true
}
return wv
}
func updateUIView(_ uiView: WKWebView, context: Context) {
uiView.load(req)
uiView.scrollView.isScrollEnabled = options.scrollEnabled
}
struct Options {
var scrollEnabled: Bool = true
var zoomEnabled: Bool = true
}
}
class WVUIScrollViewDelegate: NSObject, UIScrollViewDelegate {
let scrollEnabled: Bool
init(scrollEnabled: Bool) {
self.scrollEnabled = scrollEnabled
}
func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
scrollView.pinchGestureRecognizer?.isEnabled = scrollEnabled
}
}
class WVNavigationDelegate: NSObject, WKNavigationDelegate {
// Test to check if cookies were the issue but didn't make any difference
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
guard let response = navigationResponse.response as? HTTPURLResponse, let url = navigationResponse.response.url else {
decisionHandler(.cancel)
return
}
if let headerFields = response.allHeaderFields as? [String: String] {
let cookies = HTTPCookie.cookies(withResponseHeaderFields: headerFields, for: url)
cookies.forEach { cookie in
webView.configuration.websiteDataStore.httpCookieStore.setCookie(cookie)
HTTPCookieStorage.shared.setCookie(cookie)
}
}
decisionHandler(.allow)
}
}
In the WVNavigationDelegate
I also have a js script injected in the webview to intercept a specific call needed to detect when the booking is made but I left i out for simplicity since the problem also occurs without this code.
Are there other functionalities like the cookies I have to configure since those pages are working in Android WebViews and other browsers?
答案1
得分: 1
我遇到了同样的问题。发生在相同的时间。
其他人也遇到了类似的问题:https://learn.microsoft.com/en-us/answers/questions/1195010/ios-webkit-wkwebview-is-not-supported-to-access-th
在找到解决方案之前,我的解决办法是使用已安装的默认浏览器在应用程序之外打开特定的URL,并关闭WebView。
解决办法的代码如下:
if let bookingURL = navigationAction.request.url,
bookingURL.host == "outlook.office365.com" {
closeFunction?() // 关闭WebView
UIApplication.shared.open(bookingURL)
}
如果我有更好或真正的解决方案,我会在这里发布。
英文:
I'm having the same issue. Occurred around the same time.
Other people having similar issues: https://learn.microsoft.com/en-us/answers/questions/1195010/ios-webkit-wkwebview-is-not-supported-to-access-th
My workaround, until there is a solution, is to open this specific URL with the installed default browser outside the app and dismiss the WebView sheet therefore.
Workaround Code looks like this:
if let bookingURL = navigationAction.request.url,
bookingURL.host == "outlook.office365.com" {
closeFunction?() // dismiss WebView-Sheet
UIApplication.shared.open(bookingURL)
}
If I have a better or real solution, I will post it here.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论