MS Bookings在WKWebView中不再工作了。

huangapple go评论121阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2023年8月9日 17:08:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/76866199.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定