關于WebKit
最近接手的一個app頁面全部用H5寫的,使用的是WebKit框架。我之前寫的app也有H5頁面,不過只有兩頁,用的是webView,全H5寫app用WebKit是很有必要的,在這里推薦兩篇文章快速了解WebKit:
iOS 8 WebKit框架概覽(上)
iOS 8 WebKit框架概覽(下)
打電話失敗
然后,問題來啦。app有聯系客服功能,點擊客服電話,發現電話打不出去。
*注:電話打不出去的意思是壓根沒有調用電話這個功能,不是沒人接啊~ *
題外話: 最近電話號碼13585904041很火,我也拿來用一下
通過控制臺Log可以發現,請求失敗了:
#pragma mark 頁面加載失敗之后調用
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error
{
NSLog(@"頁面加載失敗:\n %@",error);
}
頁面加載失?。?br> Error Domain=NSURLErrorDomain Code=-1002 "unsupported URL" UserInfo={_WKRecoveryAttempterErrorKey=<WKReloadFrameErrorRecoveryAttempter: 0x7fe7f3d7a3c0>, NSErrorFailingURLStringKey=tel:13585904041, NSErrorFailingURLKey=tel:13585904041, NSUnderlyingError=0x7fe7f3d6e260 {Error Domain=kCFErrorDomainCFNetwork Code=-1002 "unsupported URL" UserInfo={NSErrorFailingURLStringKey=tel:13585904041, NSLocalizedDescription=unsupported URL, NSErrorFailingURLKey=tel:010-57745342}}, NSLocalizedDescription=unsupported URL}
看這些Log不要頭暈啊,總而言之一句話,不支持打開 tel:13585904041 這個URL,到這里,我們先復習一下打電話的代碼。
iOS打電話的代碼
方法一:
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"tel://10010"]];//打電話```
使用openURL這個API打電話結束后,返回的是系統的撥打電話界面,如何才能返回自己的應用呢?看下面的方法。
#####方法二:
使用UIWebView加載電話,這種是合法的,可以上App Store的。
UIWebView *callWebview =[[UIWebView alloc] init];
NSURL *telURL =[NSURL URLWithString:@"tel:13585904041"];
[callWebview loadRequest:[NSURLRequest requestWithURL:telURL]];
//記得添加到view上
[self.view addSubview:callWebview];
還有一種是私有方法,不能上App Store的(自己沒試過,有求真精神的可以試試然后告訴我被拒沒)。
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"telprompt://10010"]];```
到這里我們可以發現UIWebView是可以打開 tel:13585904041 的,但是,很明顯,WebKit框架里的WKWebView不支持 打開tel:XXX 這種URL。
解決方法
通過打斷點,可以發現打開一個url大概需要依次走以下代理方法(不全):
#pragma mark 在發送請求之前,決定是否跳轉
-(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
NSLog(@"在收到響應前,決定是否跳轉");
decisionHandler(WKNavigationActionPolicyAllow);//允許跳轉
}
#pragma mark 頁面開始加載時調用
-(void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation
{
NSLog(@"頁面開始加載");
}
#pragma mark 頁面加載完成之后調用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation;
{
NSLog(@"頁面加載完成");
}
#pragma mark 頁面加載失敗之后調用
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error
{
NSLog(@"頁面加載失敗:\n %@",error);
}
在加載一個頁面之前會先決定是否跳轉,我剛開始設置所有的請求都允許加載,收到@"tel:13585904041"請求后,就進到didStartProvisionalNavigation方法開始打開這個URL,然后就失敗了,所以我們需要截掉tel請求。
修改后的代理方法:
#pragma mark 在發送請求之前,決定是否跳轉
-(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
NSLog(@"在收到響應前,決定是否跳轉");
NSString *urlString = [[navigationAction.request URL] absoluteString];
urlString = [urlString stringByRemovingPercentEncoding];//解析url
if ([urlString hasPrefix:@"tel"])//截獲電話請求
{
//取消WKWebView 打電話請求
decisionHandler(WKNavigationActionPolicyCancel);
//用openURL 這個API打電話
[[UIApplication sharedApplication] openURL:[NSURL URLWithString: urlString];
}
else
{
decisionHandler(WKNavigationActionPolicyAllow);//允許其他請求
}
}
修改后就解決啦~
對純H5的吐槽
即使WebKit比WebView性能好些,但是純H5頁面還是卡死的感覺,用戶體驗很不好,兼容性也不好(快速開發的省的時間都用來調兼容了然而并沒有什么卵用),最后吐槽一句,界面好丑,一點蘋果的風格都沒了,然后,我們,決定用React Native了~