赞
踩
最近维护一个老项目时遇到的问题。说起这老项目我就有点头疼,一个快十年前的项目,这么说你可能不觉得有什么,但是你想想Swift也才发布不到十年(2014年6月发布,现2023年12月)。
项目运行在iOS 17.2设备时,应用内网页无法成功获取设置后的UserAgent
。
项目中设置UserAgent
的关键源码:
[self.webView evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id result, NSError *error) {
NSString *userAgent = [NSString stringWithFormat:@"%@", result];
NSString *newUserAgent = [userAgent stringByAppendingString:@" App/1.0.0"];
[[NSUserDefaults standardUserDefaults] registerDefaults:@{@"UserAgent": newUserAgent}];
}];
从项目源码看,设置UserAgent
是通过NSUserDefaults
实现的。大致操作如下:
WKWebView
实例对象,无需加载任何网页navigator.userAgent
获取当前的UserAgent
并修改registerDefaults
方法将修改后的UserAgent
注册到NSUserDefaults
,成为应用的默认设置WKWebView
实例对象经过以上操作,后续创建WKWebView
实例对象时都能从NSUserDefaults
中获取到修改后的UserAgent
用于初始化,从而实现全局设置。需要注意一点,registerDefaults
方法设置默认值的操作不会进行持久化存储,所以应用每次启动都需要设置一遍。
虽然理了一遍设置逻辑感觉没什么问题,但是这个方法有点老了,现在一般通过customUserAgent
属性设置,难道这个方法过时了?
为了排除其他可能存在的干扰,新建一个iOS项目用于测试,源码如下:
import UIKit import WebKit class ViewController: UIViewController, WKNavigationDelegate { private let htmlString = """ <html> <head> <meta name="viewport" content="width=device-width"> <style> button { font-size: 24px; } </style> <script> function getUserAgent() { var userAgent = navigator.userAgent; var paragraph = document.createElement('p'); paragraph.textContent = 'UserAgent: ' + userAgent; document.body.appendChild(paragraph); } </script> </head> <body style="text-align: center;"> <button οnclick="getUserAgent()">获取 UserAgent</button> </body> </html> """ private var webView: WKWebView! override func viewDidLoad() { super.viewDidLoad() // 在WKWebView初始化前设置UserAgent UserDefaults.standard.register(defaults: ["UserAgent": "App/1.0.0"]) // 创建WKWebView let webViewConfiguration = WKWebViewConfiguration() webView = WKWebView(frame: view.bounds, configuration: webViewConfiguration) webView.navigationDelegate = self view.addSubview(webView) // 加载HTML webView.loadHTMLString(htmlString, baseURL: nil) } }
iOS 17.2测试结果:
iOS 16.4测试结果:
这里补充一下,当前最新的iOS 16版本应该是iOS 16.7.3,之所以测试没用这个版本,原因有两点:
参考文档:关于 iOS 16 更新 - 官方 Apple 支持
实测iOS 17.0和iOS 17.2测试结果一样,现在基本可以确定从iOS 17开始,通过NSUserDefaults
设置UserAgent
都无法生效。初步判断,这个设置方法在iOS 17及以上过时了。个人猜测可能是WKWebView
初始化时不再从NSUserDefaults
获取默认值导致的问题(今天天太冷了,实在扛不住,后面有机会再翻翻相关源码对导致该问题的原因进一步分析)。
2024/01/01更新:如果你想进一步了解导致该问题的原因,请看这篇文章iOS问题记录 - iOS 17通过NSUserDefaults设置UserAgent无效(续)
既然这个方法失效了,那在iOS 17上通过customUserAgent
属性设置能正常生效吗?
对前面的测试源码做简单修改,页面加载完成后自动获取一次未修改的UserAgent
,然后再修改UserAgent
并通过customUserAgent
属性设置,接着手动点击按钮获取一次UserAgent
,最后对比两次获取结果判断是否设置成功。
import UIKit import WebKit class ViewController: UIViewController, WKNavigationDelegate { private let htmlString = """ <html> <head> <meta name="viewport" content="width=device-width"> <style> button { font-size: 24px; } </style> <script> function getUserAgent() { var userAgent = navigator.userAgent; var paragraph = document.createElement('p'); paragraph.textContent = 'UserAgent: ' + userAgent; document.body.appendChild(paragraph); } /* 页面加载完成后获取一次UserAgent */ window.onload = function() { getUserAgent(); }; </script> </head> <body style="text-align: center;"> <button οnclick="getUserAgent()">获取 UserAgent</button> </body> </html> """ private var webView: WKWebView! override func viewDidLoad() { super.viewDidLoad() // 创建WKWebView let webViewConfiguration = WKWebViewConfiguration() webView = WKWebView(frame: view.bounds, configuration: webViewConfiguration) webView.navigationDelegate = self view.addSubview(webView) // 加载HTML webView.loadHTMLString(htmlString, baseURL: nil) } func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { // 获取当前的UserAgent webView.evaluateJavaScript("navigator.userAgent") { (result, error) in guard let userAgent = result as? String else { return } let newUserAgent = userAgent + " App/1.0.0" // 设置UserAgent webView.customUserAgent = newUserAgent } } }
测试结果:
从测试结果看,通过customUserAgent
属性设置UserAgent
一切正常。不过这种方法不好实现全局设置,每次创建新的WKWebView
实例对象都需要再设置一遍。
通过NSUserDefaults
设置UserAgent
改为通过customUserAgent
属性设置UserAgent
,更多详情请参考前面的问题分析。
如果你只需要设置一次,还可以参考文章续篇中的方法(位于UserAgent的设置优先级
)。
如果这篇文章对你有所帮助,点赞声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。