webkit使用WKWebView來代替IOS的UIWebView和OSX的WebView,並且使用Nitro JavaScript引擎,這意味着所有第三方瀏覽器運行JavaScript將會跟safari一樣快。
第一、WKWebView增加的屬性和方法
類比UIWebView,跟UIWebView的API對比,
增加的屬性:
1、estimatedProgress 加載進度條,在IOS8之前我們是通過一個假的進度條來實現
2、backForwardList 表示historyList
3、WKWebViewConfiguration *configuration; 初始化webview的配置
增加的方法:
1、- (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration
初始化
3、(WKNavigation *)goToBackForwardListItem:(WKBackForwardListItem *)item;
跳到歷史的某個頁面
第二、相同的屬性和方法
goBack、goForward、canGoBack、canGoForward、stopLoading、loadRequest、scrollView
第三、被刪去的屬性和方法:
1、- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
在跟js交互時,我們使用這個API,目前WKWebView完檔沒有給出實現類似功能的API
2、無法設置緩存
在UIWebView,使用NSURLCache緩存,通過setSharedURLCache可以設置成我們自己的緩存,但WKWebView不支持NSURLCache
第四、delegate方法的不同
UIWebView支持的代理是UIWebViewDelegate,WKWebView支持的代理是WKNavigationDelegate和WKUIDelegate
WKNavigationDelegate主要實現了涉及到導航跳轉方面的回調方法
WKUIDelegate主要實現了涉及到界面顯示的回調方法:如WKWebView的改變和js相關內容
具體來說WKNavigationDelegate除了有開始加載、加載成功、加載失敗的API外,還具有額外的三個代理方法:
1、- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation
這個代理是服務器redirect時調用
2、- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
這個代理方法表示當客戶端收到服務器的響應頭,根據response相關信息,可以決定這次跳轉是否可以繼續進行。
3.- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
根據webView、navigationAction相關信息決定這次跳轉是否可以繼續進行,這些信息包含HTTP發送請求,如頭部包含User-Agent,Accept
個人補充:
無縫切換網頁: https://github.com/li6185377/IMYWebView/tree/master/IMYWebView
切換是遇到的坑:進度條的問題/cookie/ios8.0加載本地網頁的處理!
/**
* 將文件copy到tmp目錄(wk打開本地網頁的解決方法 8.0)wkwebview8.0系統,不支持加載本地html頁面,所以需要用以下方法修復!!
*
* @param fileURL fileURL
*
* @return
*/
- (NSURL *)fileURLForBuggyWKWebView8:(NSURL *)fileURL {
NSError *error = nil;
if (!fileURL.fileURL || ![fileURL checkResourceIsReachableAndReturnError:&error]) {
return nil;
}
// Create "/temp/www" directory
NSFileManager *fileManager= [NSFileManager defaultManager];
NSURL *temDirURL = [[NSURL fileURLWithPath:NSTemporaryDirectory()] URLByAppendingPathComponent:@"www"];
[fileManager createDirectoryAtURL:temDirURL withIntermediateDirectories:YES attributes:nil error:&error];
// 取到本地html后的錨點
NSString *lastPathComponent = [[fileURL.absoluteString componentsSeparatedByString:@"/"] lastObject];
NSURL *dstURL = [NSURL URLWithString:[temDirURL.absoluteString stringByAppendingString:lastPathComponent]];
// Now copy given file to the temp directory
[fileManager removeItemAtURL:dstURL error:&error];
[fileManager copyItemAtURL:fileURL toURL:dstURL error:&error];
// Files in "/temp/www" load flawlesly :)
return dstURL;
}
/**
* 打開本地網頁
*
* @param url
*/
- (void)loadLocalPath:(NSString *)path {
if(path){
if ([[UIDevice currentDevice].systemVersion floatValue] >= 9.0) {
// iOS9. One year later things are OK.
NSURL *fileURL = [NSURL URLWithString:[NSString stringWithFormat:@"file://%@",path]];
[self loadRequest:[NSURLRequest requestWithURL:fileURL]];
} else if ([[UIDevice currentDevice].systemVersion floatValue] < 8.0) {
// iOS8.0 以下的 走普通UIWebview
NSURL *fileURL = [NSURL URLWithString:[NSString stringWithFormat:@"file://%@",path]];
NSURLRequest *request = [NSURLRequest requestWithURL:fileURL];
[self loadRequest:request];
} else {
// iOS8. Things can be workaround-ed
// Brave people can do just this
// fileURL = try! pathForBuggyWKWebView8(fileURL)
// webView.loadRequest(NSURLRequest(URL: fileURL))
NSURL *fileURL = [self fileURLForBuggyWKWebView8:[NSURL URLWithString:[NSString stringWithFormat:@"file://%@",path]]];
NSURLRequest *request = [NSURLRequest requestWithURL:fileURL];
[self loadRequest:request];
}
}
}
cookie的添加:
NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response;
NSArray *cookies =[NSHTTPCookiecookiesWithResponseHeaderFields:[response allHeaderFields] forURL:response.URL];
for (NSHTTPCookie *cookie in cookies) {
[[NSHTTPCookieStoragesharedHTTPCookieStorage] setCookie:cookie];
}
decisionHandler(WKNavigationResponsePolicyAllow);
* kvo 觀察進度/標題 wkwebview 進度條需要添加觀察者
*/
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if([keyPath isEqualToString:@"estimatedProgress"]) {
self.estimatedProgress = [change[NSKeyValueChangeNewKey] doubleValue];
} elseif([keyPath isEqualToString:@"title"]) {
self.title = change[NSKeyValueChangeNewKey];
* 進度代理方法
*
* @param webViewProgress webViewProgress
* @param progress progress
*/
- (void)webViewProgress:(NJKWebViewProgress *)webViewProgress updateProgress:(float)progress {
// 先進行判斷,如果變化小於傳遞過來的值則賦值,因為有可能出現小於的情況
if (self.estimatedProgress <= progress) {
// 讓UIWebview的進度條也用此賦值
self.estimatedProgress = progress;
NSLog(@"webview開始完成");
[selfupdateNaviLeftButtton];
[self.webViewresetWebView];
// 只有UIWebview 加載本地html的時候會出現網頁加載完成,但是進度條不足1.0的情況,所以在完成方法中特別手動設置一下!
// 判斷是否是加載本地網頁,本地網頁沒有http
BOOL hasHttp = [[self.webView.URLabsoluteString] hasPrefix:@"http"];
if (IOS_VERSION < 8.0 && !hasHttp) {
self.webView.estimatedProgress = 1.0f;
}
_isFinish = YES;
#warning 默認設置就是NO。在ios8系統中會導致手勢問題,程序崩潰
self.allowsBackForwardNavigationGestures =YES;