iOS: 自定义 UIWebView 和 WKWebView 的 UserAgent

导言

在 iOS8, 苹果推出了 WKWebView, 目的很明显: 取代 UIWebView.

随着时间的推移, 越来越多的应用开始最低版本支持为 iOS8, 大家也纷纷的开始使用 WKWebView 组件.

在 iOS10.x 版本上, UIWebView 的表现不尽如人意, 在我们的后台日志和用户反馈, 存在很多莫名其妙的 crash 以及卡顿现象, 内存飙升等问题. 针对不同的 JS 游戏引擎, UIWebView 表现也不够好, 所以是时候使用 WKWebView 了.

但是话又说回来, 如果你最低版本支持 iOS8, 也不能完全放弃 UIWebView, WKWebView 有一部分 API 只有 iOS9+ 才有, 如果你的应用在 iOS8 运行而使用 iOS9 的 API, 肯定会 crash.

例如:

1.清除缓存.
2.设置 user-agent.

今天要说的是关于设置自定义 UIWebView 和 WKWebView 的 UserAgent 问题.

WKWebView UserAgent

默认的 UserAgent

使用下面的代码, 可以输出 WKWebView 的默认 UserAgent.

1
2
3
4
5
6
7
8
9
10
- (void)viewDidload
{
[self.wkWebView evaluateJavaScript:@"navigator.appName" completionHandler:^(id __nullable appName, NSError * __nullable error) {
NSLog(@"navigator.appName: %@", appName);
}];
[self.wkWebView evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id __nullable userAgent, NSError * __nullable error) {
NSLog(@"navigator.userAgent: %@", userAgent);
}];
}

navigator.appName 无论在 iOS8, iOS9 还是 iOS10, 输出结果都是一致的.

navigator.userAgent 在不同的 iOS 系统上面输出结果略有不同.

1
2
3
4
5
6
// iOS 8.3
// Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12F70
// iOS 9.0
// Mozilla/5.0 (iPhone; CPU iPhone OS 9_0 like Mac OS X) AppleWebKit/601.1.32 (KHTML, like Gecko) Mobile/13A4254v
// iOS 10.x
//Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Mobile/14E269

自定义 UserAgent

修改默认的 UserAgent, 需要使用下面的方法.

1
self.wkWebView.customUserAgent = @"CustomUserAgent"

这样, 就改变了其默认的 UserAgent 值了.

特别需要注意: customUserAgent 是 iOS9 之后才有的字段.

1
2
3
/*! @abstract The custom user agent string or nil if no custom user agent string has been set.
*/
@property (nullable, nonatomic, copy) NSString *customUserAgent API_AVAILABLE(macosx(10.11), ios(9.0));

所以在 iOS8.x, 如果你想改变 UserAgent, 还是要使用 UIWebView.

HTML 使用 UserAgent

HTML 中可以根据自定义的 UserAgent, 做出不同的行为, 如自定的 UserAgent 可以包括应用的版本号, HTML 可以根据不同的版本来做版本区分等逻辑.

在 HTML 中, 可以使用 JS 来获取 UserAgent 的值.

Demo.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>user-agent</title>
<script type="text/javascript">
function getUserAgent() {
var ug = navigator.userAgent;
document.getElementById("mySpan").innerHTML = ug;
}
</script>
</head>
<body>
<h1>显示 user-agent</h1>
<p><span style="font-size:30px" id="mySpan">..</span></p>
<p><input type="button" value="点击显示 user-agent" onclick="getUserAgent()" class="button"/></p>
</body>
<style>
.button {
background-color: #4C0950;
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 40px;
margin: 20px 200px 100px 300px;
cursor: pointer;
border-radius: 15;
}
</style>
</html>

使用 WKWebView 加载该 Demo.html 文件, 效果图如下:
1

UIWebView UserAgent

默认的 UserAgent

使用下面的代码, 可以输出 UIWebView 的默认 UserAgent.

1
2
3
4
5
NSString *appName = [self.webView stringByEvaluatingJavaScriptFromString:@"navigator.appName"];
NSLog(@"navigator.appName: %@", appName);
NSString *userAgent = [self.webView stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"];
NSLog(@"navigator.userAgent %@", userAgent);

打印输出结果和 WKWebView 的结果一致.

设置自定的 UserAgent

设置一个 key 为 @”UserAgent” 的本地存储即可.

1
2
3
4
5
6
7
[[NSUserDefaults standardUserDefaults] registerDefaults:@{@"UserAgent":@"CustomUserAgent-UIWebView"}];
NSString *appName = [self.webView stringByEvaluatingJavaScriptFromString:@"navigator.appName"];
NSLog(@"navigator.appName: %@", appName);
NSString *userAgent = [self.webView stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"];
NSLog(@"navigator.userAgent %@", userAgent);

这样就改变了 UIWebView 的默认 UserAgent 了.

小结

应用最低版本支持 iOS7/8 的开发者们, 可以考虑 UIWebView 和 WKWebView 并存的开发模式. iOS9及以上的开发者你们, 可以完全放弃 UIWebView, 大胆的拥抱 WKWebView 了.

移植 UIWebView 到 WKWebView 的成本不算大.
如果你现在有时间, 可以开始着手做这些事了.前端和客户端需要考虑之前交互那部分的逻辑, 即 JS 调用 Native 或者 Native 调用 JS 的需要做些调整, 因为 WKWebView 的调用方式和 UIWebView 不一样了, 前端页面要考虑版本兼容性.

新的 WKWebView 虽然存在一些坑, 但是使用它亦是大势所趋, 正所谓 存在即合理, 你没有理由拒绝它.

后续, 我会写一写在 WKWebView 上面遇到的一些问题, 分享给大家.

之前我也写过一篇文章, 是关于 UIWebView 缓存的, 不妨, 你也瞅瞅 [iOS: 聊聊 UIWebView 缓存].

坚持原创技术分享!