一、问题场景
App 打开,放置在测试中心,偶尔会出现从B页面刷新跳转到A页面。
二、问题分析
1、刚开始怀疑是否前端业务应用中有定时器,或者因为token 失效会进行跳转处理,和前端确认后没有此类代码。并且此问题在Web和 Android 端都没有,苹果端也只在那一台手机上出现。
2、fiddler 抓包
根据 全网最详细,Fiddler抓包实战 - 手机APP端https请求(超详细)_fiddler抓包手机app-CSDN博客
进行fiddler 配置和手机端代理配置,刚开始手机端使用默认的8888 端口总是无法上网,后续将fiddler 的默认端口换成了 8088 , 手机端同样配置,似乎正常了。
接着又出现:
!SecureClientPipeDirect failed: System.IO.IOException 由于远程方已关闭传输流,身份验证失败。 for pipe (CN=gateway.icloud.com.cn, O=DO_NOT_TRUST, OU=Created by http://www.fiddler2.com)
17:19:34:2393 HTTPSLint> Warning: ClientHello record was 508 bytes long. Some servers have problems with ClientHello's greater than 255
想了想是不是换了端口,这个fiddler 的ssl 证书需要重新安装更新,并且手机端也需要安装对应的证书进行信任。
这样正常可以抓包后,其实还是遇到了某些接口无法正常抓到的问题

此时可能是因为调用的接口中有对证书进 验证,发现证书的域名可能和实际的fiddler 这个证书不一致,从而导致接口返回失败造成的。这种情况的抓包还不知道要怎么处理,不过目前没有时间关注这个问题,最后确实抓到了一次页面刷新,看到的接口请求地址都是首页。
3、为了排除问题,刚开始想到的是在所有webview 有可能reload 的地方加入日志进行处理,并记录到手机沙盒里面:
#import "WebViewLogger.h"
@implementation WebViewLogger
+ (void)logWebRequest:(NSURLRequest *)request from:(NSString *)sourcePage {
NSString *logStr = @"";
if(nil == request){
logStr = [NSString stringWithFormat:@"[%@] %@ | From: %@ | URL: %@\n",
[self currentTimeString],
@"非请求",
sourcePage,
request.URL.absoluteString];
}else{
logStr = [NSString stringWithFormat:@"[%@] %@ | From: %@ | URL: %@\n",
[self currentTimeString],
request.HTTPMethod,
sourcePage,
request.URL.absoluteString];
}
NSLog(@"=====debug %@", logStr);
[self writeLogToFile:logStr];
}
+ (NSString *)currentTimeString {
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss.SSS"];
return [formatter stringFromDate:[NSDate date]];
}
+ (void)writeLogToFile:(NSString *)log {
NSString *filePath = [self logFilePath];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:filePath]) {
[fileManager createFileAtPath:filePath contents:nil attributes:nil];
}
NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:filePath];
[fileHandle seekToEndOfFile];
[fileHandle writeData:[log dataUsingEncoding:NSUTF8StringEncoding]];
[fileHandle closeFile];
}
+ (NSString *)logFilePath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths firstObject];
return [documentsDir stringByAppendingPathComponent:@"webview_requests.log"];
}
@end
但是复现问题后发现都是正常加载逻辑,没有任何异常地方会去重新刷新。然后自己还在某个地方手机添加了一次reload 的操作,抓取日志后,发现即使reload 也不会到首页,而是带有菜单路由的当前页面,所以排除是异常导致的reload 逻辑造成此问题。
4、由于问题复现的场景只在测试中心,还是怀疑到网络来了,无心中增加了网络检测的回调日志,发现果然有输出:

在网络变化十秒钟之后就出现了重载的日志。
三、破局
经过如上分析后,慢慢定位就是网络变化导致的重载,然后想起代码中之前有一个适配App首次使用网络授权的处理逻辑。
iOS 10 的坑:新机首次安装 app,请求网络权限"是否允许使用数据"(转) - 那一抹风情 - 博客园

CTCellularData *cellularData = [[CTCellularData alloc]init];
CTCellularDataRestrictedState state = cellularData.restrictedState;
if(state == kCTCellularDataNotRestricted){
}else{
cellularData.cellularDataRestrictionDidUpdateNotifier = ^(CTCellularDataRestrictedState state) {
if (state == kCTCellularDataRestricted) {
NSLog(@"networkAuthStatus 用户选择网络使用受限制");
} else if (state == kCTCellularDataNotRestricted) {
NSLog(@"networkAuthStatus 用户选择网络使用不受限制");
} else {
NSLog(@"networkAuthStatus 网络权限使用未知");
}
dispatch_async(dispatch_get_main_queue(), ^{
[self processViewLoadDependNetwork];
});
};
}
而测试中心的那台手机在那个办公室就经常会触发这个回调,当手动开关蜂窝网络的时候也能够复现,但是具体那哪些场景会触发这个回调,这个还是不太清楚,后续让测试复测,发现关闭蜂窝网络,wifi 变化也可能会触发这个回调,只能说这个网络授权的适配还是挺让折磨人的,一个问题又耗费了将近两天的时间来分析。