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的添加:

wkwebview 和http不共享cookie,所以在请求的时候拿不到cookie!
 
 
所以在loadRequset的时候需要给请求设置cookie
{
        NSMutableURLRequest *requestNew = [NSMutableURLRequest requestWithURL:request.URL];
        [requestNew addValue:[YZTWebView readCurrentCookie:request.URL] forHTTPHeaderField:@"Cookie"];
        return [(WKWebView *)self.realWebView loadRequest:requestNew];
}
 
但是还存在一个问题,cookie只会设置一次,假如网页间的跳转用到了ajax,这样cookie就会失效,需要需要在wk的didFinishNavigation方法中手动编写js代码去设置cookie!
还需要注意的问题就是js写的cookie需要设定path。path不同的话cookie也设置不了!
/**
 *  wkwebview 加载完成
 */
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    
    //取出cookie
    NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
    //js函数
    NSString *JSFuncString =
    @"function setCookie(name,value,expires)\
    {\
    var oDate=new Date();\
    oDate.setDate(oDate.getDate()+expires);\
    document.cookie=name+'='+value+';expires='+oDate+';path=/'\
    }\
    function getCookie(name)\
    {\
    var arr = document.cookie.match(new RegExp('(^| )'+name+'=([^;]*)(;|$)'));\
    if(arr != null) return unescape(arr[2]); return null;\
    }\
    function delCookie(name)\
    {\
    var exp = new Date();\
    exp.setTime(exp.getTime() - 1);\
    var cval=getCookie(name);\
    if(cval!=null) document.cookie= name + '='+cval+';expires='+exp.toGMTString();\
    }";
    
    //拼凑js字符串
    NSMutableString *JSCookieString = JSFuncString.mutableCopy;
    for (NSHTTPCookie *cookie in cookieStorage.cookies) {
        NSString *excuteJSString = [NSString stringWithFormat:@"setCookie('%@', '%@', 1);", cookie.name, cookie.value];
        [JSCookieString appendString:excuteJSString];
    }
    //执行js
    [webView evaluateJavaScript:JSCookieString completionHandler:nil];
    
    [self callback_webViewDidFinishLoad];
}
 
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
    NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response;
    NSArray *cookies =[NSHTTPCookiecookiesWithResponseHeaderFields:[response allHeaderFields] forURL:response.URL];
   
    for (NSHTTPCookie *cookie in cookies) {
        [[NSHTTPCookieStoragesharedHTTPCookieStorage] setCookie:cookie];
    }
   
    decisionHandler(WKNavigationResponsePolicyAllow);
}
 
进度条问题:
WKWeb和UIWeb使用进度条的时候用estimatedProgress ,这个属性是Wk独有的,但是UIWeb的时候也给这个值去赋值,这样就可以一起使用这个属性,在控制器中去用kvo检测这个值!
 
WK中检测进度条的方法:
/**
 *  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];
    }
 
UIWe
/**
 *  进度代理方法
 *
 *  @param webViewProgress webViewProgress
 *  @param progress        progress
 */
- (void)webViewProgress:(NJKWebViewProgress *)webViewProgress updateProgress:(float)progress {
   
    // 先进行判断,如果变化小于传递过来的值则赋值,因为有可能出现小于的情况
    if (self.estimatedProgress <= progress) {
        // 让UIWebview的进度条也用此赋值
        self.estimatedProgress = progress;
    }
 
 
然后在外部的控制器去kvo检测。
坑:
在控制器的did finish中:
- (void)webViewDidFinishLoad:(UIWebView *)webView {
    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;

iOS8 无缝切换WKWebView,借鉴IMYWebview,解决进度条,cookie,本地页面等问题的更多相关文章

  1. iOS UIWebView 加载进度条的使用-WKWebView的使用,更新2017.6.26

    1.由于项目中加载网络插件,直接使用了webview加载.使用了三方NJKWebViewProgress进度条的使用,近期在测试时发现,网络缓慢时出现白屏,有卡顿现象. 于是采用了WKWebView进 ...

  2. C#编程总结(四)多线程应用(进度条的编程问题)——转自http://www.cnblogs.com/yank/p/3232955.html

    多线程应用 多线程应用很广泛,简单总结了一下: 1)不阻断主线程,实现即时响应,由后台线程完成特定操作2)多个线程,完成同类任务,提高并发性能3)一个任务有多个独立的步骤,多个线程并发执行各子任务,提 ...

  3. ASP.Net 上传进度条的实现方法

    对于加载时间比较长的ASP.NET页面,我们可以在客户端浏览器中显示进度条来显示页面正在装载.下面就是具体的实现过程: 新建项目,名字为WebPortal,在项目类型中选择Visual C#项目或者V ...

  4. Ajax上传文件进度条显示

    要实现进度条的显示,就要知道两个参数,上传的大小和总文件的大小 html5提供了一个上传过程事件,在上传过程中不断触发,然后用已上传的大 小/总大小,计算上传的百分比,然后用这个百分比控制div框的显 ...

  5. 不可思议的纯 CSS 滚动进度条效果

    结论先行,如何使用 CSS 实现下述滚动条效果? 就是顶部黄色的滚动进度条,随着页面的滚动进度而变化长短. 在继续阅读下文之前,你可以先缓一缓.尝试思考一下上面的效果或者动手尝试一下,不借助 JS , ...

  6. 【css系列】创建网页加载进度条

    一.最简单或者明显的方式是使用定时器 1.在网页中加入布局覆盖真实网页内容 2.使用定时器确定加载所用时间的长短,其实并不是真正的加载进度实现 <!DOCTYPE html> <ht ...

  7. vue使用nprogress页面加载进度条

    vue使用nprogress页面加载进度条 NProgress是页面跳转是出现在浏览器顶部的进度条 官网:http://ricostacruz.com/nprogress/ github:https: ...

  8. php实现进度条原理

    PHP实现进度条的原理: 模版替换,在页面设置一个标识,轮子自己的页面,不发请求给服务器,由服务器端获得进度,然后替换该页面标识,达到进度条效果. 页面代码: 1 2 3 4 5 6 7 8 9 10 ...

  9. 学习 | css3实现进度条加载

    进度条加载是页面加载时的一种交互效果,这样做的目的是提高用户体验. 进度条的的实现分为3大部分:1.页面布局,2.进度条动效,3.何时进度条增加. 文件目录 加载文件顺序 <link rel=& ...

随机推荐

  1. 什么是虚拟环境、为什么使用虚拟环境、Anaconda创建、激活、退出、删除虚拟环境

    一.虚拟环境 virtual environment 它是一个虚拟化,从电脑独立开辟出来的环境.通俗的来讲,虚拟环境就是借助虚拟机docker来把一部分内容独立出来,我们把这部分独立出来的东西称作“容 ...

  2. 笔记:webpack 打包参数 mode development

    webpack 打包参数 mode development 在开发时使用 webpack 打包后不压缩,所以只需要在 webpack 打包命令中加上 --mode mode development 即 ...

  3. oracle之 利用 controlfile trace文件重建控制文件

    一. 11g RAC 重建控制文件 1. --"create controlfile"命令生成到追踪文件中:alter database backup controlfile to ...

  4. bzoj1040(ZJOI2008)骑士——基环树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1040 基环树的模板. 套路就是把环断开,先把一端作为根节点,强制不选:再把另一端作为根节点, ...

  5. 解决openoffice进程异常退出的办法:

    实现以守护进程,定时检测openoffice是否退出,如果进程不存在,通过脚本将openoffice起起来即可.   具体操作步骤: 第一步: 将openoffice.sh脚本放置在root目录下面, ...

  6. 扩充 jQuery EasyUI Datagrid 数据行鼠标悬停/离开事件(onMouseOver/onMouseOut)

    客户需求: jQuery EasyUI Datagrid 用户列表鼠标悬停/离开数据行时显示人员头像(onMouseOver/onMouseOut) 如图所示,Datagrid 鼠标悬停/离开数据行时 ...

  7. Linux GNU C

    Linux 系统上可用的C编译器是GNU C编译器,它建立在自由软件基金会的编程许可证的基础上,因此可以自由发布.GNU C对标准C 进行一系列扩展,以增强标准C的功能. 1.零长度数组GNU C 允 ...

  8. pandas之DateFrame 数据过滤+遍历行+读写csv-txt-excel

    # XLS转CSV df = pd.read_excel(r'列表.xls') df2 = pd.DataFrame()df2 = df2.append(list(df['列名']), ignore_ ...

  9. python2.7 + ubuntu14.4 + dlib19.7

    0.首先需要Cmake以及编译C++成python程序的工具 sudo apt-get install libboost-python-dev cmake 1.download dlib19.7 fr ...

  10. Emacs golang用户代码无法补全问题

    现象:Emacs使用company-go可以正常补全标准库函数和go get安装库函数:而对于自已写的代码,只能补全当前包下的变量和函数. 原因:company-go后台是使用了gocode,而goc ...