在APP中,H5页面可以通过加载vConsole脚本,来查看页面的日志、异常、网络加载、设备信息、储存信息、元素。但是,JS脚本加载于页面Dom挂载之后,这样就会使得这一区间的信息丢失,而且vConsole的Error也会有采集不到的情况。
本篇先简单讲述WKWebView的加载流程,再通过Safari网页检查器,实现H5页面的调试与问题定位。
WKWebViewConfiguration配置
- (WKWebViewConfiguration *)configuration {
if (!_configuration) {
_configuration = [[WKWebViewConfiguration alloc] init];
_configuration.allowsInlineMediaPlayback = YES;
if (@available(iOS 10.0, *)) {
if ([_configuration respondsToSelector:@selector(mediaTypesRequiringUserActionForPlayback)]) {
_configuration.mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone;
}
} else if(@available(iOS 9.0, *)){
if([_configuration respondsToSelector:@selector(setRequiresUserActionForMediaPlayback:)]) {
_configuration.requiresUserActionForMediaPlayback = NO;
}
} else if([_configuration respondsToSelector:@selector(setMediaPlaybackRequiresUserAction:)]){
_configuration.mediaPlaybackRequiresUserAction = NO;
}
WKUserContentController* userContentController = [[WKUserContentController alloc] init];
_configuration.userContentController = userContentController;
NSString *strDocumentCookie = @"document.cookie='uid=;path=/;domain=.baidu.com';document.cookie='sessionId=;path=/;domain=.baidu.com';document.cookie='tokenId=;path=/;domain=.baidu.com';";
WKUserScript* cookieScript = [[WKUserScript alloc] initWithSource:strDocumentCookie injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
[userContentController addUserScript:cookieScript];
}
return _configuration;
}
WKWebView的初始化
- (WKWebView *)wkWebView {
if (!_wkWebView){
_webViewWK = [[WKWebView alloc] initWithFrame:self.frame configuration:self.configuration];
_wkWebView.scrollView.showsHorizontalScrollIndicator = NO;
_wkWebView.scrollView.showsVerticalScrollIndicator = NO;
_wkWebView.scrollView.bounces = NO;
_wkWebView.navigationDelegate = self;
_wkWebView.UIDelegate = self;
_wkWebView.allowsBackForwardNavigationGestures = YES;
_wkWebView.configuration.allowsInlineMediaPlayback = YES;
if (@available(iOS 11.0, *)) {
_wkWebView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
return _wkWebView;
}
- (void)loadRequest {
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://m.baidu.com"]];
[request setValue:@"uid=;sessionId=;tokenId=;" forHTTPHeaderField:@"Cookie"];
[self.wkWebView loadRequest:request];
}
// 开始加载
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation;
// 资源加载,可以进行拦截处理
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler WK_SWIFT_ASYNC(3);
// 加载响应,可以进行拦截处理
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler WK_SWIFT_ASYNC(3);
// 加载失败
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error;
// 加载完成
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation;
// web进程终止
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView API_AVAILABLE(macos(10.11), ios(9.0));
1)H5到iOS的交互
在页面开始加载时,注入JSBridge
[self.configuration.userContentController addScriptMessageHandler:(MKMessageHandler *)scriptMessageHandler name:@"JSBridge"];
MessageHandler的具体实现
@interface MKMessageHandler : NSObject
@end
@implementation MKMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
if ([message.body isKindOfClass:[NSDictionary class]]) {
NSDictionary *messageBody = [NSDictionary getDictionary:message.body];
NSString *moduleName = [messageBody stringForKey:@"moduleName"];
NSString *methodName = [messageBody stringForKey:@"methodName"];
NSString *parameter = [messageBody stringForKey:@"parameter"];
[self performMainThread:^ {
[self invokeAPI:moduleName methodName:methodName parameter:parameter];
}];
}
}
- (void)invokeAPI:(NSString *)moduleName methodName:(NSString *)methodName parameter:(NSString *)parameter {
// API映射
}
@end
web端调用JSAPI
window.webkit.messageHandlers.JSBridge.postMessage({'moduleName': 'page','methodName':'openURL','parameter':JSON.stringify({'url':''})})
2)iOS到H5的交互
web端方法挂载,监听方法回调
// 页面window挂载方法
window.onCallBack = res => {
console.log(res)
}
/* 使用function的方式,this会指向window
window.onCallBack = function(res) {
console.log(res)
}
*/
webView直接运行JS代码调用
[self.wkWebView evaluateJavaScript:@"window.onCallBack('Hello JS!!!')" completionHandler:^(id result, NSError *error) {
// 调用结果回调
}];
1)iOS安装包必须是开发证书打的IPA包
2)打开手机的设置 > Safari > 高级 > 网页检查器
3)打开Mac版Safari偏好设置 > 高级 > 在菜单栏中显示“开发”菜单
4)手机连接Mac电脑 > 打开APP对应的web页 > 打开Mac版Safari的“开发”菜单
5)找到对应的页面 > 点击打开网页检查器
1)元素布局:手动修改html以及css属性,点击刷新按钮可以重置页面。通过网页检查器修改元素布局与样式,可以直接应用在APP的web页面。
2)控制台:通过错误日志排查页面异常,使用控制台运行JS代码。错误日志包括js语法错误、脚本资源加载异常、页面Exception。
3)来源:找到需要调试的JS文件,在具体的行打上断点,当页面逻辑调用到指定行代码时,触发断点;在通过变量预览、断点操作、控制台操作来实现基本的联调。
4)网络:查看网络资源的加载情况(资源大小、url、时耗、类型、异常),包括XHR接口的相关信息(请求、响应)。
5)储存空间:LocalStorage、Cookie、SessionStorage,查看页面相关的存储信息。