WKWebView使用遇到的坑

作者: Jay神 | 来源:发表于2016-01-19 11:06 被阅读48297次

    1. ios9以前版本读取本地HTML的问题

    当使用loadRequest来读取本地的HTML时,WKWebView是无法读取成功的,后台会出现如下的提示:
    Could not create a sandbox extension for /
    原因是WKWebView是不允许通过loadRequest的方法来加载本地根目录的HTML文件
    而在iOS9的SDK中加入了以下方法来加载本地的HTML文件:
    [WKWebView loadFileURL:allowingReadAccessToURL:]
    但是在iOS9以下的版本是没提供这个便利的方法的。以下为解决方案的思路,就是在iOS9以下版本时,先将本地HTML文件的数据copy到tmp目录中,然后再使用loadRequest来加载。但是如果在HTML中加入了其他资源文件,例如js,css,image等必须一同copy到temp中。这个是最蛋疼的事情了。

    解决方法如下

    1.Objective-C:

    //将文件copy到tmp目录
    - (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];
        
        NSURL *dstURL = [temDirURL URLByAppendingPathComponent:fileURL.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;
    }
    
    //调用逻辑
     NSString *path = [[NSBundle mainBundle] pathForResource:@"indexoff" ofType:@"html"];
        if(path){
            if ([[UIDevice currentDevice].systemVersion floatValue] >= 9.0) {
                // iOS9. One year later things are OK.
                NSURL *fileURL = [NSURL fileURLWithPath:path];
                [self.webView loadFileURL:fileURL allowingReadAccessToURL:fileURL];
            } 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.fileHelper fileURLForBuggyWKWebView8:[NSURL fileURLWithPath:path]];
                NSURLRequest *request = [NSURLRequest requestWithURL:fileURL];
                [self.webView loadRequest:request];
            }
        }
    

    2.Swift

    //将文件copy到tmp目录
    func fileURLForBuggyWKWebView8(fileURL: NSURL) throws -> NSURL {
        // Some safety checks
        var error:NSError? = nil;
        if (!fileURL.fileURL || !fileURL.checkResourceIsReachableAndReturnError(&error)) {
            throw error ?? NSError(
                domain: "BuggyWKWebViewDomain",
                code: 1001,
                userInfo: [NSLocalizedDescriptionKey: NSLocalizedString("URL must be a file URL.", comment:"")])
        }
    
        // Create "/temp/www" directory
        let fm = NSFileManager.defaultManager()
        let tmpDirURL = NSURL.fileURLWithPath(NSTemporaryDirectory()).URLByAppendingPathComponent("www")
        try! fm.createDirectoryAtURL(tmpDirURL, withIntermediateDirectories: true, attributes: nil)
    
        // Now copy given file to the temp directory
        let dstURL = tmpDirURL.URLByAppendingPathComponent(fileURL.lastPathComponent!)
        let _ = try? fileMgr.removeItemAtURL(dstURL)
        try! fm.copyItemAtURL(fileURL, toURL: dstURL)
    
        // Files in "/temp/www" load flawlesly :)
        return dstURL
    }
    
    //方法调用
    
        var filePath = NSBundle.mainBundle().pathForResource("file", ofType: "pdf")
    
        if #available(iOS 9.0, *) {
            // iOS9. One year later things are OK.
            webView.loadFileURL(fileURL, allowingReadAccessToURL: fileURL)
        } else {
            // iOS8. Things can be workaround-ed
            //   Brave people can do just this
            //   fileURL = try! pathForBuggyWKWebView8(fileURL)
            //   webView.loadRequest(NSURLRequest(URL: fileURL))
            do {
                fileURL = try fileURLForBuggyWKWebView8(fileURL)
                webView.loadRequest(NSURLRequest(URL: fileURL))
            } catch let error as NSError {
                print("Error: " + error.debugDescription)
            }
        }
    

    2. WKWebView - WKNavigationDelegate使用

    特别提醒一点,在使用以下delegate的方法时

    - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
    

    需执行decisionHandler的block。

    例如:

    - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
        
        NSURLRequest *request = navigationAction.request;
        WMPageActionType actionType = ActionTypeNone;
        WKNavigationActionPolicy actionPolicy = WKNavigationActionPolicyAllow;
        if([request.URL.absoluteString hasPrefix:OC_CLOSE_REQUEST]){
            actionType = ActionTypeClose;
            actionPolicy = WKNavigationActionPolicyCancel;
        }
        if(self.actionDelegate && [self.actionDelegate respondsToSelector:@selector(webView:action:type:)]) {
            [self.actionDelegate webView:webView action:navigationAction type:actionType];
        }
       //这句是必须加上的,不然会异常
        decisionHandler(actionPolicy);
    }
    

    3.WKWebView-JS执行方法

    WKWebView JS执行方法与UIWebView不一样了。

    - (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^)(id, NSError *))completionHandler;  
    

    completionHandler 拥有两个参数,一个是返回错误,一个可以返回执行脚本后的返回值

    相关文章

      网友评论

      • IT播客:设置 navigationDelegate 会黑屏 咋回事啊?
      • 有理想有暴富的小青年:[self.wkwebView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:urlStr]]];
        用这个加载本地的html试试
      • Beyond无状态:博主 我wkwebview访问网络HTML地址 就第一次能加载出来 重跑一遍项目就不行了 换个HTML地址 也是这样 咋回事啊
      • 宇玄丶:楼主,你那个fielHeper是什么啊?
      • 5a8c365da0b7:请问WKWebView苹果审核时说ipv6网络不能加载,有没有人遇到过?
      • 069eea124da3:博主,请问self.fileHelper指的是什么?
      • 2bb5ebfd832c:博主我想问下,如果是ios8系统中使用wkwebview,为什么接收不到WKScriptMessageHandler回调中的-(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message 而在ios9之后的系统就可以正常的接收到
      • ce70df11c8e3:朋友,我在iOS10.2系统上可以使用[webView loadRequest:[NSURLRequest requestWithURL:fileURL]];
        你说的 WKWebView是不允许通过loadRequest的方法来加载本地根目录的HTML文件这个有问题?
        麻烦你再验证一下
      • 潘烨:我这个wKwebView 跟js 交互,轻点一下不触发js的方法,在模拟器上必须摁下去才能触发,真机上也是,怎么能轻点一下就能触发,是不是有什么属性,获取js 设置啊,JSContext *content 这个轻点是可以的,求大神帮忙啊。
      • 748281001c95:怎么更改wkWebview页面字体大小,还有无图模式呢?
      • 小伙eryayayayaya:楼主:可以问你一个问题么,我有这么一个需求:有一个界面使用H5做的,这个h5界面有一个倒计时,当倒计时时间还有10秒的时候,就让他有提示声音。控制这个声音开关是要用原声的switch来控制。这种要怎么做?
      • f48ab9e63152:请问我是用远程下载html页面 然后用loadhtmlstring()的方式加在的html页面, 也碰到楼主的问题, 请问如何解决? js, css都是远程路径.
      • 太空蛙:大神们, wkwebview出现白屏怎么破?
      • 9a996ce6ed8d:关于wkWebview和js交互的问题, evaluateJavaScript:comletionHandler 这个方法中,返回结果一个是NSError类型的error,另一个id类型的结果为什么是一个Boolean属性,是这个方法只能返回这两个类型的结果吗
      • ZhongXi:- (nullable WKNavigation *)loadFileURL:(NSURL *)URL allowingReadAccessToURL:(NSURL *)readAccessURL API_AVAILABLE(macosx(10.11), ios(9.0));
        可以加载本地HTML文件
      • 1b05ef2b4848:请教下楼主 咱们用wkwebview的这个代理方法 接受前端的调用
        “- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message”
        比如说前端想跟客户端获取用户信息的话 客户端接收到信息之后 该怎么返回相应的信息呢?
        之前uiwebview 我们可以直接retuan相应的信息
      • 米米露:博主你好,我用了您的方法,把文件拷贝到tmp目录下可以加载出来,但是tmp目录下的文件会被清除。然后就拷贝到document目录下,但是document目录下却打不开。请问您有什么解决办法吗?
        德坤柳:@哈尔_e451 你后来是怎么解决的啊
        Jay神:document没权限 简单界面用wk 复杂的还是回到webview比较合适
        哈尔_e451:你好,请问你是怎么解决的?Tmp目录文件会被清空,放到这里显然不好
      • 始于__初见:使用WKWebview 控制台输出
        Could not signal service com.apple.WebKit.WebContent: 113: Could not find specified service
        Could not signal service com.apple.WebKit.Networking: 113: Could not find specified service
        有遇到么
        始于__初见:@Mossion 没有呢 ,正常使用没有问题
        Mossion:@始于__初见 请问你解决这个问题没有
        我不是掌柜:@始于__初见 +1,不知道什么情况
      • vicky_菲:我想问一下WKWebView加载的页面字体过大,如何调整?
        vicky_菲:@Jay神 谢谢 :+1:
        vicky_菲:设置了preferences.minimumFontSize = 30.0;注释掉就好了
        Jay神:字体问题 跟wk没关系 得看你加载的界面内容
      • 皮乐皮儿:楼主,我遇到了这样的问题:前天一切还是正常的,昨天开始测试的时候忽然发现WKWebView加载网页出现了问题,在模拟器上一切正常,在真机上就不能加载了,系统是iOS10.1.1的,换成uiwebview没什么问题,这个是什么原因呢?
        皮乐皮儿:@sculg 看下是不是html文件中调用css的路径不对,html和js,css文件最好放到同一个路径下 <link type="text/css" rel="stylesheet" href="css名称"> 我的这个里面是这样处理的。我遇到的问题不是你这样的,是由于webview高度获取,本来是js返回的,但是需要获取两次,第一次获取到后不会高度显示不完全,需要过一两秒重新获取一次才可以,这个问题目前用的笨方法,隔一秒再获取一次
        sculg:@顾语流年 你好,你的这个问题解决了吗?我也出现了这个问题,加载本地文件,模拟器上一切正常,真机上只能显示html文件,css样式无法显示出来。
      • FLNuo:还有 你最后这个completionHandler 方法 我的怎么 没有 势必自定义的???
      • FLNuo:WKWebView 加载html的时候 不走html中调用的js!是怎么回事啊?
        41219c59cd08:我的也是加载不了js,css,请问您是怎么解决的?
        FLNuo:@Jay神 对的 自己写的 js代码
        Jay神:加载本地js吗
      • GiantAxe77:WKWebView的哪个方法和UIWebView的shouldStartLoadWithRequest:方法一样啊?
        6ea8c6a1d65d:@GiantAxe decidePolicyForNavigationAction
      • 飞天遁地:我用wkwebView加载本地html,显示不全是什么问题?
      • z_hy:使用WKWebview在js中使用了zepto.js 的 load()方法,然后就报了一个跨域失败的错误 xmlhttprequest cannot load file cross origin requests are only,请问有什么解决办法么?
      • 6e8179322f95:如何在wkwebview加载完成后,获取网页的真实高度?
      • 7d4bb5d59ee5:我用wkwebview加载本地html文件loadrequest(loadHTML也试过,一样),之后要隔0.3-0.5秒左右才调用didFinishNavigation,求问是什么问题
        82295265a0fd:@Jay神 把html文件已经复制到tmp下了,还报Could not create a sandbox extension for '/'警告,但是会到加载完成的代理,然后发送向js发送evaluateJavaScript这个方法,报error错误, Error Domain=WKErrorDomain Code=4 "发生 JavaScript 异常" UserInfo=0x155a36c0 {NSLocalizedDescription=发生 JavaScript 异常},只有ios8下会这样,ios9以上没事
        7d4bb5d59ee5:@Jay神 应该不大啊,html文件才100多行,还有一些js,css,jquery文件
        Jay神:@Pandexxxxxxxxxx 本地的HTML很大吗?
      • 长期接iOS外包:博主,请问您一下,为什么我是用模态跳转的方式跳到wkWebView加载内容,因为系统有默认的返回方式,就好像UIModalPresentationCurrentContext这种方式,我点击WkWebView的上面就可以返回上层页面,但是这一返回就崩了,这种情况不知道你有没遇到过,但使用UIWebView是没有任何问题的
        82295265a0fd:@Jay神 把html文件已经复制到tmp下了,还报Could not create a sandbox extension for '/'警告,但是会到加载完成的代理,然后发送向js发送evaluateJavaScript这个方法,报error错误, Error Domain=WKErrorDomain Code=4 "发生 JavaScript 异常" UserInfo=0x155a36c0 {NSLocalizedDescription=发生 JavaScript 异常}
        长期接iOS外包:@Jay神 不像是其他地方引起的
        Jay神:@ISO_iOS_OSI 这个没遇到,但如何返回不应该回崩!有其他的业务在跑而引起的吗?
      • fc18f69e6ff0:之前webview拨打电话是可以实现的,现在换成wkwebview之后拨打电话怎么实现
        年轻人的心情_爱我所爱:@闭上眼睛 我也想问这个问题,楼上解决了吗
      • 4a8aeec7b5f2::fearful:求解一个坑,情景:wkwebview 加载服务器一个h5页面,h5页面里面有ajax请求 问题:这个页面经常会加载不出来,偶尔又可以加载出来,链接拷贝到浏览器可以加载出来
        长期接iOS外包:楼主,请问您一下,为什么我是用模态跳转的方式跳到wkWebView加载内容,因为系统有默认的返回方式,就好像UIModalPresentationCurrentContext这种方式,我点击WkWebView的上面就可以返回上层页面,但是这一返回就崩了,这种情况不知道你有没遇到过,但使用UIWebView是没有任何问题的
        Jay神:Ajax返回结果后有什么操作
      • 小_曹:博主,请问在执行JS的时候报错 Error Domain=WKErrorDomain Code=4 "A JavaScript exception occurred" UserInfo={NSLocalizedDescription=A JavaScript exception occurred} 怎么解决呢
        _skye:想咨询下 这个问问题目前解决了没有?
        AgoniNemo:你是不是在userContentController方法里,用evaluateJavaScript方法执行js?
      • Sky521:WKWebView通过loadHTMLString这个方法加载html字符串,改变字体大小,博主有方法吗
        卧龙小:@Sky521 解决了没?才用@天地不仁以万物为刍狗 的方案吗?
        798a37d82543:@Sky521
        if (self.note) {
        NSString *path = [[NSBundle mainBundle] bundlePath];
        NSURL *baseURL = [NSURL fileURLWithPath:path];
        NSString *css = @"<meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no'> <link rel='stylesheet' type='text/css' href='amazeui.min.css' > <link rel='stylesheet' type='text/css' href='app.css' >";
        NSString *subStr = [css stringByAppendingString:self.note];
        [webView loadHTMLString:subStr baseURL:baseURL];
        }
        self.note 是你需要加载的html字符串
        引入amazeui.min.css(自己下载)就差不多了,我这还引入了一个app.css,还是样式上的调整:body{padding:15px
        }//内边距
        img{
        width:100%
        }//图片适应屏幕
        Jay神:这个需求有多奇葩?这样做的目的是什么?我想如果要通过这种方式实现字体大小不合适
      • 0de50e9952cd:同样问题 但是我有个更简单方法诶
        [self loadHtml:@"File"];
        -(void)loadHtml:(NSString*)name{
        NSString *filePath = [[NSBundle mainBundle]pathForResource:name ofType:@"html"];
        NSString * str = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
        [self.webView loadHTMLString:str baseURL:nil];
        }
        zyg:@东方_未明 指定 baseURL 就行呀
        例如:[self.webView loadHTMLString:html baseURL:[NSBundle mainBundle].resourceURL];
        东方_未明:@贵妃醉酒 试了试你的方法, 果然加载不到js和css
        Jay神:@贵妃醉酒 HTML里面引用的其它文件怎么办?例如js或者image
      • 0141904cfe54:thanks for sharing
      • b01c913b01b1:我想知道如何监听网页跳转到的url地址?
        Jay神:@光影色 看WKNavigationDelegate
      • midmirror:感谢博主分享,帮了大忙了。。
      • 问问问你:那么如果都是一个个文件夹的内容,改如何copy到temp目录下呢?
        440bd488f596:@Jay神 :flushed: 请问楼主什么事hybird的框架
        Jay神:如果这样要批量的 你在APP启动时就要导入了 还有你有这么大量的页面的话 为何还用wk,应该选择hybird的框架去设计APP了
      • 良年追影:iOS8 wkwebview 加载远程html不显示图片,只显示内容,这是什么原因呢,求帮忙
        大爷你的伞:真的是这样啊,加载本地的HTML图片也显示不了,图片不是本地的
        Jay神:@良年追影 这个应该不会这样,加载本地图片,如果图片不在tmp路径才可能无法显示呢。
      • WenJim::action:

      本文标题:WKWebView使用遇到的坑

      本文链接:https://www.haomeiwen.com/subject/btukkttx.html