聊一聊 WKWebView UserAgent 的相关姿势
一般情况下,
web
端的同学通过UA
来区分当前浏览器是在PC
还是Mobile
或者App
内,所以在App
内设置UA
就是必须要做的事情。
1. 通过 UserDefaults 设置
由于WKWebView
有一个特性,在初始化时会获取UserDefaults
中UserAgent
这个key的值,这需要我们在真正使用的WKWebView
之前要创建一个WKWebView
获取他默认的UA;
webView = WKWebView();
webView?.evaluateJavaScript("navigator.userAgent", completionHandler: { (obj: Any?, error: Error?) in
guard let ua = obj as? String else {
return
}
let customUA = "\(ua) Custom User Agent"
UserDefaults.standard.register(defaults: ["UserAgent": customUA])
UserDefaults.standard.synchronize()
})
2. 通过 WKWebView.customUserAgent 设置
这种方式其实和第1种方式并没有什么差别,而且还比较复杂,因为只对这一个WebView
有效,最关键的是这是一个异步执行js的代码,可能时间上会有些迟,虽然可以把异步转为同步。
还有一个坑点是之前我们没有通过navigator.userAgent
先获取,再设置,而是直接设置了WKWebView.customUserAgent
的值,导致并没有附带UA
原有的值,这样web
端的同学就拿不到浏览器的相关信息了。
let fakeWebView = WKWebView();
fakeWebView.evaluateJavaScript("navigator.userAgent", completionHandler: { (obj: Any?, error: Error?) in
guard let ua = obj as? String else {
return
}
let customUA = "\(ua) Custom User Agent"
let realWebView = WKWebView()
realWebView.customUserAgent = customUA
})
3. 通过 applicationNameForUserAgent 设置
-
config
的此属性与上一个属性不同,不是将设置的字符串完全变成你所设置的值。 -
它将字符串集添加到
WebView
的默认UserAgent
并执行它。 -
这正好就是我们想要的,我们所要做的就是设置要添加的字符串。
-
修改后的
UserAgent
,如:Mozilla/5.0 (iPhone; CPU iPhone OS 13_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Custom UserAgent
let config = WKWebViewConfiguration()
config.applicationNameForUserAgent = "Custom User Agent"
let webview = WKWebView(frame: .zero, configuration: config)
4. 系统采用的优先级
customUserAgent > UserDefault > applicationNameForUserAgent
- 左侧优先级高于右侧。
- 如果设置了
customUserAgent
或UserDefaults
方法,则applicationNameForUserAgent
将被忽略。 applicationNameForUserAgent
仅添加到了webview
具有的默认UserAgent
中。
5. 关于 iPadOS 13 的特殊情况
5.1 问题
在 iPadOS 13
以上,WKWebView
的UserAgent
变成了类似这样:
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko)
其主要原因是iPadOS
在设置-Safari浏览器-请求桌面网站-所有网站
的设置默认是开启的,只要把它关掉就正常了,但是不能要求用户去做这个设置。
5.2 解决方案
WKWebView
中新增的api
中有个WKWebpagePreferences
:
@property (null_resettable, nonatomic, copy) WKWebpagePreferences *defaultWebpagePreferences API_AVAILABLE(macos(10.15), ios(13.0));
typedef NS_ENUM(NSInteger, WKContentMode) {
WKContentModeRecommended,
WKContentModeMobile,
WKContentModeDesktop
} API_AVAILABLE(ios(13.0));
WK_EXTERN API_AVAILABLE(macos(10.15), ios(13.0))
@interface WKWebpagePreferences : NSObject
@property (nonatomic) WKContentMode preferredContentMode API_AVAILABLE(ios(13.0));
@end
我们只需要在初始化的时候按下面的方式设置,就可以设置WKWebpagePreferences
的preferredContentMode
为WKContentModeMobile
,这样iPadOS
上的UserAgent
就正常了:
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
if (@available(iOS 13.0, *)) {
configuration.defaultWebpagePreferences.preferredContentMode = WKContentModeMobile;
}
UA
就变为了:Mozilla/5.0 (iPad; CPU OS 13_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko)