WKWebView设置UserAgent踩坑

WKWebView设置UserAgent踩坑

通过下面的方法给wkwebview设置自定义useragent,解决了常见的问题,如第一次设置不生效,第一次获取不到原来的useragent等问题

思路如下

单个webview设置:iOS9.0以后,可以设置customUserAgent来单个设置webview的自定义useragent

全局设置:先通过evaluateJavaScript("navigator.userAgent")获取原来的useragent,然后追加自定义useragent,通过UserDefaults.standard.register(defaults: ["UserAgent": newAgent])全局设置

代码如下
import UIKit
import WebKit

class WebViewManager: NSObject {
    static let shared = WebViewManager()
    var webView: WKWebView?
    private var isAddCustomUserAgent: Bool = false
    
    func loadHtmlString(_ htmlString: String) {
        // 单个设置webview的userAgent
//        addCustomUserAgent()
//        webView?.loadHTMLString(htmlString)
//        webView?.evaluateJavaScript("navigator.userAgent") { (oldAgent, error) in
//            guard let oldAgent = oldAgent as? String else {
//                print("没取到oldAgent")
//                return
//            }
//            print("设置后的新的user agent:\(oldAgent)")
//        }
        
        // 全局设置userAgent
        addCustomUserAgent { [weak self] in
            // 一定要在useragent设置完成后在加载html页面
            self?.webView?.loadHTMLString(htmlString)

            self?.webView?.evaluateJavaScript("navigator.userAgent") { (oldAgent, error) in
                guard let oldAgent = oldAgent as? String else {
                    print("没取到oldAgent")
                    return
                }
                print("设置后的新的user agent:\(oldAgent)")
            }
        }
    }
}

extension WebViewManager {
    // 单个webview设置useragent
    private func addCustomUserAgent() {
        let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? ""
        let token = Authentication.shared.user?.accessToken ?? ""
        let refreshToken = Authentication.shared.user?.refreshToken ?? ""
        let customUserAgent = ";POSApp;platform=iOS;version=\(version);token=\(token);refreshToken=\(refreshToken)"
        webView?.customUserAgent = customUserAgent
    }
    
    // 全局设置useragent
    private func addCustomUserAgent(completed: @escaping ()->()) {
        guard !isAddCustomUserAgent else {
            print("不再重新设置agent")
            completed()
            return
        }

        // 这个地方使用evaluateJavaScript的webview一定要添加到界面的,不然取不到oldAgent
        webView?.evaluateJavaScript("navigator.userAgent") { [weak self] (oldAgent, error) in
            let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? ""
            let token = Authentication.shared.user?.accessToken ?? ""
            let refreshToken = Authentication.shared.user?.refreshToken ?? ""
            let customUserAgent = ";POSApp;platform=iOS;version=\(version);token=\(token);refreshToken=\(refreshToken)"
            
            guard let oldAgent = oldAgent as? String else {
                print("evaluateJavaScript取不到旧的agent")
                let oldAgent = "Mozilla/5.0 (\(UIDevice.current.model); CPU iPhone OS \(UIDevice.current.systemVersion.replacingOccurrences(of: ".", with: "_")) like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148"
                let newAgent = "\(oldAgent)\(customUserAgent)"
                // 设置global User-Agent
                UserDefaults.standard.register(defaults: ["UserAgent": newAgent])
                // 一定要设置customUserAgent,因为全局useragent只会在设置后添加的webview生效
                self?.webView?.customUserAgent = newAgent
                
                self?.isAddCustomUserAgent = true
                print("evaluateJavaScript设置新的agent:\(newAgent)")
                
                completed()
                return
            }
            
            guard !oldAgent.hasSuffix(customUserAgent) else {
                print("evaluateJavaScript已经设置新的agent")
                completed()
                return
            }
            
            let newAgent = "\(oldAgent)\(customUserAgent)"
            UserDefaults.standard.register(defaults: ["UserAgent": newAgent])
            // 一定要设置customUserAgent,因为全局useragent只会在设置后添加的webview生效
            self?.webView?.customUserAgent = newAgent
            
            self?.isAddCustomUserAgent = true
            print("evaluateJavaScript设置新的agent:\(newAgent)")
            
            completed()
        }
    }
}

补充

真是too long too simple (_)v

这样设置有两个个坑
1、切换useragent某些场景下也会失效。
2、第一次安装app,进入webview,设置useragent会失效;

没搞清楚具体原因是什么,但是找到了解决办法:
1、加载时强制不适用任何缓存

let request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData) 
webView?.load(request)
webView?.reloadFromOrigin()

2、调用load后再设置一次customUserAgent

webView?.customUserAgent = customUserAgent
loadHTMLString(("\(self.webHostUrlString)\(self.htmlPath ?? "")"))
webView?.customUserAgent = customUserAgent

后来发现完全是多此一举了,其实是web端的bug

3、先获取原来的,再追加

private func addCustomUserAgent(completed: @escaping ()->()) {
        self.fakeWebView = WKWebView()
        self.fakeWebView?.evaluateJavaScript("navigator.userAgent") { [weak self] (oldAgent, error) in
            self?.fakeWebView = nil
            guard let oldAgent = oldAgent as? String else {
                let oldAgent = "Mozilla/5.0 (\(UIDevice.current.model); CPU iPhone OS \(UIDevice.current.systemVersion.replacingOccurrences(of: ".", with: "_")) like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148"
                let newAgent = "\(oldAgent)\(self?.customUserAgent ?? "")"
                self?.webView?.customUserAgent = newAgent
                completed()
                return
            }
            
            let newAgent = "\(oldAgent)\(self?.customUserAgent ?? "")"
            self?.webView?.customUserAgent = newAgent
            completed()
        }
    }

好了,问题总算比较完美的解决了^ - ^

你可能感兴趣的:(WKWebView,iOS原创,webview,ios)