前言

客户端界面嵌了 H5,做了混合开发。点击原生的按钮跳到了一个 WebView,再点击 H5 里某个按钮又要可以跳回原生界面。由于 H5 的页面已经在公众号正常运营,需要判断当前打开页面的环境,如果是 App,JS 的点击事件改为调用原生。最后我们采用修改 UserAgent 来做标识。

定义

User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等

打开火狐页面开发调试command + shift + g 如图所示:

获取UserAgent

UIWebView 和 WKWebView 与 JS 交互的方法有点区别,UIWebView 是同步的,而 WKWebView 是异步的。

  • UIWebView :
NSString *oldUserAgent = [[[UIWebView alloc]init] stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"];
  • WKWebView:
[self evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id _Nullable result, NSError * _Nullable error) {NSString *oldUserAgent = result;
}];

默认UserAgent

以下是我的模拟器 iPhone 11s Pro Max,iOS 13.3.3 获取到的UserAgent。

Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148/requestByNative

无论使用 UIWebView 方式还是 WKWebView 方式,获取到的结果是一样的。也就是说,获取 UserAgent 不区分
webView 是哪个控件哪个内核。

修改全局UserAgent值(这里是在原有基础上拼接自定义的字符串)

  • UIWebView :

1.如果想要统一自定义 UserAgent 让所有的 webView 访问网页时都生效,可以在 App 启动的时候,修改全局 UserAgent。
2.还可以用单利只设置一次

+ (void)registUserAgent {static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{UIWebView *webView = [[UIWebView alloc]initWithFrame:CGRectZero];//修改UserAgentNSString *oldUserAgent = [webView stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"];//自定义需要拼接的字NSString *newUserAgent = [oldUserAgent stringByAppendingString:@"xxx"];NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:newUserAgent, nil];[[NSUserDefaults standardUserDefaults] registerDefaults:dictionary];[[NSUserDefaults standardUserDefaults] synchronize];});}userAgent 为默认 oldUserAgent。
newUserAgent 首先拼接了XXX ,标识比如,版本号,功能类别
  • WKWebView:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{[self p_dealWithUserAgent];return YES;
}// 获取默认User-Agent- (void)p_dealWithUserAgent{[self.wkWebView evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id result, NSError *error) {NSString *oldAgent = result;if ([CMBCBLStringUtil strNilOrEmpty:oldAgent]) {return;}NSRange rangeUa = [oldAgent rangeOfString:_webViewConfig.webUA];NSString *uaSuffix = [NSString stringWithFormat:@"%@%@",webUA,releaseVersion];// 如果仅仅设置一次UA,设置UA后重新关闭浏览器才会生效if(rangeUa.location == NSNotFound){NSString *newAgent = [NSString stringWithFormat:@"%@/%@",oldAgent,uaSuffix];NSDictionary *dictionnary = @{@"UserAgent":newAgent};[[NSUserDefaults standardUserDefaults] registerDefaults:dictionnary];[[NSUserDefaults standardUserDefaults] synchronize];if (@available(iOS 9.0, *)) {[self.wkWebView setCustomUserAgent:newAgent];}}}];}

oldAgent 为默认 oldUserAgent。
newAgent 首先拼接了XXX ,标识比如,版本号,功能类别

虽然一样可以实现,但我不推荐使用这种方式,因为它是异步的。也就是必须要先声明个 property,调用 self.wkWebView = wkWebView; 把 wkWebView 保存起来。否则 block 回调时,这个 wkWebView 对象已经销毁了,回调的参数也都是 nil。

  1. App启动时获取系统默认UserAgen进行存储。
  2. 使用WebView之前,对存储的默认UserAgent进行修改,通过
    registerDefaults:方法注册到内存中。
  3. WebView实例的时候从内存中拿到我们修改的userAgent。

修改局部UserAgent

有时候只有部分页面访问的时候需要改 UserAgent,或者不同页面访问的时候需要修改不同的 UserAgent,这个时候就只能在加载页面前进行修改。

  • UIWebView :
/** 修改UIWebView的UserAgent */
- (void)changeUIWebViewUserAgent
{/** 修改UIWebView的UserAgent */
- (void)changeUIWebViewUserAgent
{self.webView = [[UIWebView alloc] initWithFrame:self.view.bounds];[self.view addSubview:self.webView];//修改UserAgent[self changeUIWebViewUserAgent];[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.whoishostingthis.com/tools/user-agent/"]]];
}}

切记要在 - loadRequest: 之前修改。

注意,有时候把方法的调用写在 - loadRequest: 下面也没问题。这只是偶然,因为加载页面也是异步的,有时候会有延迟,实际上改 UserAgent 的代码执行完了才加载完页面。如果网速极端好的情况,就会出现 UserAgent 设置无效的问题。

还要注意,获取并修改 userAgent 的 webView 对象,跟加载网页的 webView 不能是同一个对象

我调用 - changeUIWebViewUserAgent 在方法内部重新初始化了一个 webView 对象去获取并修改 userAgent ,而 self.webView 则负责加载网页,两者不是同一个对象。否则,就会出现第一次设置 UserAgent 会无效的问题。

  • WKWebView:
    UIWebView修改+WKWebView加载

建议使用 UIWebView 的方式修改 UserAgent 后,再使用 WKWebView 加载网页,这样就很简单,使用起来跟 UIWebView 一样。

/** 修改WKWebView的UserAgent */
- (void)changeWKWebViewUserAgent
{self.wkWebView = [[WKWebView alloc] initWithFrame:self.view.bounds];[self.view addSubview:self.wkWebView];//UIWebView *webView = [[UIWebView alloc]initWithFrame:CGRectZero];//修改UserAgentNSString *oldUserAgent = [webView stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"];//自定义需要拼接的字NSString *newUserAgent = [oldUserAgent stringByAppendingString:@"xxx"];NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:newUserAgent, nil];[[NSUserDefaults standardUserDefaults] registerDefaults:dictionary];[[NSUserDefaults standardUserDefaults] synchronize];[self.wkWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.whoishostingthis.com/tools/user-agent/"]]];
}

纯WKWebView修改+加载

/** 修改WKWebView的UserAgent */
- (void)changeWKWebViewUserAgent
{WKWebView *wkWebView = [[WKWebView alloc] initWithFrame:CGRectZero];self.wkWebView = wkWebView;__weak typeof(self) weakSelf = self;[wkWebView evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id result, NSError *error) {NSString *userAgent = result;NSString *newUserAgent = [userAgent stringByAppendingString:@" origin/sfddjapp"];NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:newUserAgent, @"UserAgent", nil];[[NSUserDefaults standardUserDefaults] registerDefaults:dictionary];__strong typeof(weakSelf) strongSelf = weakSelf;dispatch_async(dispatch_get_main_queue(), ^{// 重新初始化WKWebViewstrongSelf.wkWebView = [[WKWebView alloc] initWithFrame:self.view.bounds];[strongSelf.view addSubview:self.wkWebView];[strongSelf.wkWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.whoishostingthis.com/tools/user-agent/"]]];});}];
}

这里也一样有坑,调用获取并修改 UserAgent 的 wkWebView 对象和加载页面的 wkWebView 必须是不同的对象,也就是在回调里需要重新初始化 wKWebView。否则就会出现设置 UserAgent 无效的问题,大概也就是网上说的,“要第二次才会显示自定义的值”。

顺带一提,iOS9 出了新的 API

@property (nullable, nonatomic, copy) NSString *customUserAgent
API_AVAILABLE(macosx(10.11), ios(9.0));

可以直接修改 WKWebView 的 UserAgent。即使在WebView实例之后

[self.wkWebView setCustomUserAgent:newUserAgent];

但是我们还是需要适配 iOS8

思考

每次启动App,都会是系统默认的UserAgent,而调用[[NSUserDefaults standardUserDefaults]
registerDefaults:dictionary];修改后再次获得的UserAgent都是修改后的UserAgent???

结论

我们修改的UserAgent是存在在内存当中,每次App重启就都会获取到硬盘中存在的UserAgent。

后记

总而言之,不管是 UIWebView 还是 WKWebView,获取到的 UserAgent 是一样的。如果要做到最简单最通用,就用 UIWebView 的方式获取并修改 UserAgent。还有注意,修改 UserAgent 之前获取 UserAgent 的 webView 对象,和修改之后调用加载网页的 webView 对象,不能是同一个对象,否则会出现第一次设置无效的问题。

注意:

  1. 所以最好不要完全自定义 UserAgent,而是在默认的 UserAgent 后,拼接上所需要的自定义标识即可。

iOS修改WebView的UserAgent相关推荐

  1. IOS修改设备用户代理UserAgent

    用户代理 User Agent,是指浏览器,它的信息包括硬件平台.系统软件.应用软件和用户个人偏好 在UIWebView的一个代理方法里面,可以查看当前设备的UserAgent - (BOOL)web ...

  2. IOS修改webView背景透明以及IOS调用前台js的方法

    工作上遇到IOS的webView中的H5页面需要透明以显示webView的背景颜色.用H5自身的透明度的css样式或者js控制背景颜色及透明度都打不到想要的效果,最后还是通过ios设置webView中 ...

  3. iOS 修改webView字体

    五中方案 UIFont *font = [UIFont systemFontOfSize:12];//方法一NSString *fontColor =@"CCCCFF";NSStr ...

  4. iOS 修改webView字体大小,设置宽度及缩放效果

    1.设置字体大小 -(void)webViewDidFinishLoad:(UIWebView *)webView {[webView stringByEvaluatingJavaScriptFrom ...

  5. html ua ios,iOS 修改默认 UserAgent

    前言: 有个项目需求,要区分打开H5是在本地APP还是在手机浏览器,前端伙伴说需要配合修改默认的 UserAgent,以便区分. 一.如何获取UserAgent UIWebView方式: UIWebV ...

  6. 修改Chrome的UserAgent

    修改Chrome的UserAgent 直接在chrome商店中搜索user-agent switcher 打开chrome 商店,搜索 user-agent switcher 点击免费, 然后执行安装 ...

  7. iOS 修改项目名称

    2019独角兽企业重金招聘Python工程师标准>>> 1. [代码]iOS 修改项目名称 1 2. [图片] 1.png 3. [图片] 2.png 4. [图片] 3.png 5 ...

  8. IOS 修改UIAlertController的按钮标题的字体颜色,字号,内容

    IOS 修改UIAlertController的按钮标题的字体颜色,字号,内容 UIAlertController *alertVC = [UIAlertController alertControl ...

  9. 解决ios的webview中上/下拉露出黑灰色背景问题

    解决ios的webview中上/下拉露出黑灰色背景问题 问题描述:手机H5页面在ios的webview中,下拉(或上拉)会露出黑灰色背景 ,感觉很不好看,现在想要去掉这个背景 解决方法: 1.touc ...

最新文章

  1. 私有云的优缺点_2019年中国云计算行业竞争格局与发展趋势分析「图」
  2. 有1,2,3,4四个数字,能组成多少个互不相同且无重复数字的三位数 都是多少
  3. linux脚本格式模板,Linux Shell 常见的命令行格式简明总结
  4. 基于JAVA+SpringBoot+Mybatis+MYSQL的送水公司后台管理系统
  5. 编写一个程序,要求输入一个ASCII码值(如66),然后输入相应的字符`
  6. Jenkins部署java项目实例
  7. [转] 39万的一节课:让你悟透“近朱者赤,近墨者黑”的道理
  8. TypeScript:函数进阶
  9. 上传图片方法大全 [网摘]
  10. web.config中文解释
  11. python怎么读取dat类型文件_基于python批量处理dat文件及科学计算方法详解
  12. mysql备份管家婆_管家婆怎么恢复数据,备份数据
  13. scan函数函数用法详解
  14. Python“Non-ASCII character 'xe5' in file”报错问题(转)
  15. 贵如油的春雨都是润物细无声的么?——记2021年首场大范围雷雨强对流天气
  16. 查找共家庭组计算机,家庭组多台电脑共享方法
  17. MIT-6.s081-CodeWalk-fs.cfile.csysfile.c
  18. Tensorflow2——Eager模式简介以及运用
  19. oracle导入.dmp,oracle导入.dmp脚本
  20. 数据结构中的L=(List)malloc(sizeof(PtrToNode));是什么意思

热门文章

  1. html 挺帅抽奖的效果
  2. 计算机快捷键如何移动到桌面图标,Win7系统计算机图标拖动到任务栏的方法
  3. 听声辨物,这是AI视觉该干的???|ECCV 2022
  4. macOS运行软件提示:“无法打开“xxx.app”,因为无法验证开发者。”
  5. 聊聊后端Web开发框架(Python)的简单使用
  6. 最大公约数的四种方法
  7. 平安人寿多模态合成AI视频机器人:行业首个具备大规模应用能力的多模态合成机器人 | 百万人学AI评选
  8. uni-app 25后端api开发和前后端交互(51-60)
  9. 音视频系列---最强播放器推荐
  10. FOFA(一): FOFA入门