WKWebView的customUserAgent
WKWebView有一个属性customUserAgent/*! @abstract The custom user agent string or nil if no custom user agent string has been set.*/@property (nullable, nonatomic, copy) NSString *customUserAgent API_AVAI...
属性customUserAgent
WKWebView有一个属性customUserAgent
/*! @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));
问题1
在一次使用webView的时候出现了这样一个问题:在iOS9上加载显示空白,iOS12上加载显示成功,但是加载的不是手机上的网页,而是网页版。
网页版:
手机版:
可以看出同一个链接地址,手机版和网页版区别还是很大的,手机上我们需要加载手机版网页,才能显示正常。
找了找问题,后来发现是设置customUserAgent位置不当导致的。
起初我在创建webView的时候直接设置customUserAgent:
self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config];
self.webView.UIDelegate = self;
self.webView.navigationDelegate = self;
//self.webView.customUserAgent = @"xxx";//bug,切勿再此设置,切记在didFinishNavigation处设置。
NSURLRequest *request = [NSURLRequest requestWithURL:self.webURL];
[self.webView loadRequest:request];
[self.view addSubview:self.webView];
后来将这里的设置注释掉,发现加载就正常了,iOS9加载正常,iOS12也加载正常,而且加载的是手机版页面,而不是网页版。
虽然现实正常了,但是js端小伙伴要用到userAgent判断是哪一个端,iOS,安卓还是h5,所以就还是需要设置userAgent,将设置放在网页加载成功后设置:
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation {
NSLog(@"webView load finished");
webView.customUserAgent = @"xxx";
}
这里不设置userAgent的话,js端是不会把事件回调给OC端的,因为我们的js根据userAgen判断是哪一个端,然后js交互调用不同的方法传进行传值。如果js端不用这个userAgent的话不用设置也可以。
思考
为什么我们在创建webView的时候设置userAgent,有些机型会加载H5的网页而不是手机浏览器的网页内容?
这就得知道userAgent的作用是什么,浏览器通过userAgent来判断是哪一端,百度“移动和pc userAgent判断”。
我们在创建webView的时候给userAgent赋值,这样的话,覆盖了原有的userAgent的值,导致浏览器无法判断是pc端还是手机端,所以在手机上加载了pc上的网页。
再看一下customUserAgent这个属性在文档中的描述,如果我们设置,原customUserAgent的值就会被覆盖。
关于customUserAgent
作用
其他端用customUserAgent来判断是是哪一端,pc端还是手机端。
读customUserAgent的值
在webView未加载出来前获取webView的customUserAgent,会获取不到。只有loading之后才能获取到值,获取办法:
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation
{
NSLog(@"webView load finished");
[self.loadingView stopAnimating];
//设置userAgent
[self.webView evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
NSString *newUserAgent = [NSString stringWithFormat:@"%@iphone iOS xxx",result];
self.webView.customUserAgent = newUserAgent;
NSLog(@"customUserAgent : %@",self.webView.customUserAgent);
}];
}
通过js方法获取userAgent,回调里的result即userAgent。
打印了两个手机的userAgent
iPhone6
Mozilla/5.0 (iPhone; CPU iPhone OS 12_1_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/16D57i phonexxx
iPhoneX
Mozilla/5.0 (iPhone; CPU iPhone OS 12_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148i phonexxx
iPadAri3 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko)
iPhone11模拟器 Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
需要设置App Transport Security Settings。
上面的设置方式在新一些的iOS版本中可能会存在customUserAgent字符串被重复的拼接 iphone iOS xxx 的问题,较早一些的版本我还没发现这个问题,今天发现是在iOS 14上,重新来编辑一下笔记。
使用下面的方式来设置,避免多次重复的设置和多次拼接我们需要添加的字符串。
例如我们要加一个版本号
NSString *versionIdentifier = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleVersionKey]
[webView evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
if (![result containsString:versionIdentifier]) {
NSString *deviceIdentifier = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) ? @"iPad" :@"iPhone";
webView.customUserAgent = [NSString stringWithFormat:@"%@^%@^%@",result,deviceIdentifier,versionIdentifier];
}
NSLog(@"user-Agent : %@",webView.customUserAgent);
}];
调试一下就知道是什么问题,该怎么处理了,很简单,不赘述。
设置customUserAgent
上面我们获取到userAgent后,使用NSString *newUserAgent = [NSString stringWithFormat:@"%@iphonevhallclass",result];
拼接了一段“iphone iOS xxx”,这个跟js商量好就行。这样设置不会覆盖userAgent原有值。
问题2
H5的小伙伴需要在网页加载前就用userAgent,要判断是iOS还是安卓或者是pc。
感觉这种网页没加载就要userAgent的值的做法不是很合理,网页未加载前我们拿不到userAgent的值,如果设置成别的值就会出现userAgent被覆盖问题。
self.webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 20, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame)-20) configuration:config];
self.webView.UIDelegate = self;
self.webView.navigationDelegate = self;
self.webView.allowsBackForwardNavigationGestures = YES;
self.webView.customUserAgent = @"Mozilla/5.0 (iPhone; CPU iPhone OS 12_1_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/16D57 iphone iOS xxx";
直接用了iPhone6的userAgent后面拼接上’iphone iOS xxx‘,在开始创建的时候直接设置上了。
这是个投机的解决办法,最好不要这样,H5的同学还有没有其他的办法呢?非得网页加载前就用userAgent?这合理吗?
更多推荐
所有评论(0)