美文网首页iOS收藏
iOS 加载WKWebView

iOS 加载WKWebView

作者: th先生 | 来源:发表于2018-08-26 17:02 被阅读923次

    WKWebView是苹果在iOS 8之后推出的框架WebKit中的浏览器控件, 其加载速度比UIWebView快了许多, 但内存占用率却下降很多, 也解决了加载网页时的内存泄露问题.

    WKWebView的属性
    /// webView的自定义配置
    
    @property (nonatomic,readonly, copy) WKWebViewConfiguration *configuration;
    
    /// 导航代理
    
    @property (nullable, nonatomic, weak)id <WKNavigationDelegate> navigationDelegate;
    
    /// UI代理
    
    @property (nullable, nonatomic, weak)id <WKUIDelegate> UIDelegate;;
    
    /// 访问过网页历史列表
    
    @property (nonatomic,readonly, strong) WKBackForwardList *backForwardList;
    
    /// 自定义初始化
    
    - (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration NS_DESIGNATED_INITIALIZER;- (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;
    
    /// url加载webView视图
    
    - (nullable WKNavigation *)loadRequest:(NSURLRequest *)request;
    
    /// 文件加载webView视图
    
    - (nullable WKNavigation *)loadFileURL:(NSURL *)URL allowingReadAccessToURL:(NSURL *)readAccessURL API_AVAILABLE(macosx(10.11), ios(9.0));
    
    /// HTMLString字符串加载webView视图
    
    - (nullable WKNavigation *)loadHTMLString:(NSString *)stringbaseURL:(nullable NSURL *)baseURL;
    
    /// NSData数据加载webView视图
    
    - (nullable WKNavigation *)loadData:(NSData *)data MIMEType:(NSString *)MIMEType characterEncodingName:(NSString *)characterEncodingName baseURL:(NSURL *)baseURL API_AVAILABLE(macosx(10.11), ios(9.0));
    
    /// 返回上一个网页节点
    
    - (nullable WKNavigation *)goToBackForwardListItem:(WKBackForwardListItem *)item;
    
    /// 网页的标题, 一般使用KVO动态获取
    
    @property (nullable, nonatomic,readonly, copy) NSString *title;
    
    /// 页面加载进度, 一般使用KVO动态获取
    @property (nonatomic, readonly) double estimatedProgress;
    
    /// 网页的URL地址
    
    @property (nullable, nonatomic,readonly, copy) NSURL *URL;
    
    /// 网页是否正在加载
    
    @property (nonatomic,readonly, getter=isLoading) BOOL loading;
    
    /// 加载的进度 范围为[0, 1]
    
    @property (nonatomic,readonly)double estimatedProgress;
    
    /// 网页链接是否安全
    
    @property (nonatomic,readonly) BOOL hasOnlySecureContent;
    
    /// 证书服务
    
    @property (nonatomic,readonly, nullable) SecTrustRef serverTrust API_AVAILABLE(macosx(10.12), ios(10.0));
    
    /// 是否可以返回
    
    @property (nonatomic,readonly) BOOL canGoBack;
    
    /// 是否可以前进
    
    @property (nonatomic,readonly) BOOL canGoForward;
    
    /// 返回到上一个网页
    
    - (nullable WKNavigation *)goBack;
    
    /// 前进到下一个网页
    
    - (nullable WKNavigation *)goForward;
    
    /// 重新加载
    
    - (nullable WKNavigation *)reload;
    
    /// 忽略缓存 重新加载
    
    - (nullable WKNavigation *)reloadFromOrigin;
    
    /// 停止加载
    
    - (void)stopLoading;
    
    /// 执行JavaScript
    
    - (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void(^ _Nullable)(_Nullableid, NSError * _Nullable error))completionHandler;
    
    /// 是否允许左右滑动,返回-前进操作  默认是NO
    
    @property (nonatomic) BOOL allowsBackForwardNavigationGestures;
    
    /// 自定义代理字符串
    
    @property (nullable, nonatomic, copy) NSString *customUserAgent API_AVAILABLE(macosx(10.11), ios(9.0));
    
    /// 在iOS上默认为NO,标识不允许链接预览
    
    @property (nonatomic) BOOL allowsLinkPreview API_AVAILABLE(macosx(10.11), ios(9.0));
    
    /// 滚动视图, WKWebView继承自UIView, 所以如果想设置scrollView的一些属性, 需要对此属性进行配置
    
    
    @property (nonatomic,readonly, strong) UIScrollView *scrollView;
    
    /// 是否支持放大手势,默认为NO
    
    @property (nonatomic) BOOL allowsMagnification;
    
    /// 放大因子,默认为1
    
    @property (nonatomic) CGFloat magnification;
    
    /// 据设置的缩放因子来缩放页面,并居中显示结果在指定的点
    
    - (void)setMagnification:(CGFloat)magnification centeredAtPoint:(CGPoint)point;/// 证书列表@property (nonatomic,readonly, copy) NSArray *certificateChain API_DEPRECATED_WITH_REPLACEMENT("serverTrust", macosx(10.11,10.12), ios(9.0,10.0));
    
    
    WKWebView的常用方法:
    // 带配置信息的初始化方法
    // configuration 配置信息
    - (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration
    // 加载请求
    - (nullable WKNavigation *)loadRequest:(NSURLRequest *)request;
    // 加载HTML
    - (nullable WKNavigation *)loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL;
    // 返回上一级
    - (nullable WKNavigation *)goBack;
    // 前进下一级, 需要曾经打开过, 才能前进
    - (nullable WKNavigation *)goForward;
    // 刷新页面
    - (nullable WKNavigation *)reload;
    // 根据缓存有效期来刷新页面
    - (nullable WKNavigation *)reloadFromOrigin;
    // 停止加载页面
    - (void)stopLoading;
    // 执行JavaScript代码
    - (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;
    
    
    WKWebView的使用
    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
    
    config.selectionGranularity = WKSelectionGranularityDynamic;
    
    config.allowsInlineMediaPlayback = YES;
    
    WKPreferences *preferences = [WKPreferences new];
    
    //是否支持JavaScript
    
    preferences.javaScriptEnabled = YES;
    
    //不通过用户交互,是否可以打开窗口
    
    preferences.javaScriptCanOpenWindowsAutomatically = YES;
    
    config.preferences = preferences;
    
    // 创建UserContentController(提供JavaScript向webView发送消息的方法)
        WKUserContentController* userContent = [[WKUserContentController alloc] init];
        // 添加消息处理,注意:self指代的对象需要遵守WKScriptMessageHandler协议,结束时需要移除
        [userContent addScriptMessageHandler:self name:@"NativeMethod"];
        // 将UserConttentController设置到配置文件
        config.userContentController = userContent;
    
    WKWebView *webview = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, KScreenHeight - 64) configuration:config];
    
    [self.view addSubview:webview];
    
    /* 加载服务器url的方法*/
    
    NSString *url = @"https://www.baidu.com/";
    
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
    
    [webview loadRequest:request];
    
    webview.navigationDelegate = self;
    
    webview.UIDelegate = self;
    
    
    #pragma mark - WKNavigationDelegate
    /* 页面开始加载 */
    - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{
    }
    /* 开始返回内容 */
    - (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{
         
    }
    /* 页面加载完成 */
    - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
         
    }
    /* 页面加载失败 */
    - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation{
         
    }
    /* 在发送请求之前,决定是否跳转 */
    - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
    
      NSURL *url =  navigationAction.request.URL;
        
        NSString *urlStr = url.absoluteString;
        NSLog(@"【load url】=== %@", urlStr);
       //不允许跳转
       //decisionHandler(WKNavigationActionPolicyCancel);
       //return;
    
        //允许跳转
        decisionHandler(WKNavigationActionPolicyAllow);
        
    }
    /* 在收到响应后,决定是否跳转 */
    - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
         
        NSLog(@"===%@",navigationResponse.response.URL.absoluteString);
        //允许跳转
        decisionHandler(WKNavigationResponsePolicyAllow);
        //不允许跳转
        //decisionHandler(WKNavigationResponsePolicyCancel);
    }
    
    // 接收到服务器跳转请求之后调用
    
    - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation {
    
        NSLog(@"-------接收到服务器跳转请求之后调用");
    
    }
    
    // 数据加载发生错误时调用
    
    - (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error {
    
        NSLog(@"----数据加载发生错误时调用");
    
    }
    
    // 需要响应身份验证时调用 同样在block中需要传入用户身份凭证
    
    - (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void(^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler {
    
        //用户身份信息    NSLog(@"----需要响应身份验证时调用 同样在block中需要传入用户身份凭证");
    
        NSURLCredential *newCred = [NSURLCredential credentialWithUser:@""                                                          password:@""                                                      persistence:NSURLCredentialPersistenceNone];
    
        // 为 challenge 的发送方提供 credential    [[challenge sender] useCredential:newCred forAuthenticationChallenge:challenge];
    
        completionHandler(NSURLSessionAuthChallengeUseCredential,newCred);
    
    }
    
    // 进程被终止时调用
    
    - (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView {
    
        NSLog(@"----------进程被终止时调用");
    
    }
    
    
    自定义配置

    WKUserContentController 是JavaScript与原生进行交互的桥梁, 主要使用的方法有:

    // 注入JavaScript与原生交互协议
    
    // JS 端可通过 window.webkit.messageHandlers.<name>.postMessage(<messageBody>) 发送消息
    - (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name;
    // 移除注入的协议, 在deinit方法中调用
    - (void)removeScriptMessageHandlerForName:(NSString *)name;
    
    

    实现WKScriptMessageHandler协议方法:

    JavaScript调用原生方法

    - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    
      // 判断是否是调用原生的  
    
        if([@"NativeMethod" isEqualToString:message.name]) { 
    
            // 判断message的内容,然后做相应的操作   
    
            if([@"close" isEqualToString:message.body]) {
    
            }
    
         }
    
    }
    在 message的name和body属性中我们可以获取到与JS调取原生的方法名和所传递的参数。
    

    注意:上面将当前ViewController设置为MessageHandler之后需要在当前ViewController销毁前将其移除,否则会造成内存泄漏。

    [self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"NativeMethod"];
    

    原生调用JS方法

    // iosImg 为js方法名,后面跟的是参数
    
    NSString *promptCode = [NSString stringWithFormat:@"iosImg('%@','%@')",self.picType,longStr];
        
        [_webView evaluateJavaScript:promptCode completionHandler:^(id object,NSError *error) {
            
            NSLog(@"=======%@",error);
            
        }];
    
    WKUIDelegate代理方法

    web界面中有弹出警告框时调用
    这个代理方法, 主要是用来处理使用系统的弹框来替换JS中的一些弹框的,比如: 警告框, 选择框, 输入框,

    /**
     webView中弹出警告框时调用, 只能有一个按钮
    
     @param webView webView
     @param message 提示信息
     @param frame 可用于区分哪个窗口调用的
     @param completionHandler 警告框消失的时候调用, 回调给JS
     */
    
    - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(void(^)())completionHandler {
    
        NSLog(@"-------web界面中有弹出警告框时调用");
    
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"警告" message:message preferredStyle:(UIAlertControllerStyleAlert)];
        UIAlertAction *ok = [UIAlertAction actionWithTitle:@"我知道了" style:(UIAlertActionStyleDefault) handler:^(UIAlertAction * _Nonnull action) {
            completionHandler();
        }];
        
        [alert addAction:ok];
        [self presentViewController:alert animated:YES completion:nil];
    
    
    }
    
    

    下面这些方法是交互JavaScript的方法

    // JavaScript调用confirm方法后回调的方法 confirm是js中的确定框,需要在block中把用户选择的情况传递进去
    /** 对应js的confirm方法
     webView中弹出选择框时调用, 两个按钮
    
     @param webView webView description
     @param message 提示信息
     @param frame 可用于区分哪个窗口调用的
     @param completionHandler 确认框消失的时候调用, 回调给JS, 参数为选择结果: YES or NO
     */
    
    -(void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void(^)(BOOL))completionHandler {
    
        NSLog(@"%@",message);
    
        completionHandler(YES);
    
    /*
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"请选择" message:message preferredStyle:(UIAlertControllerStyleAlert)];
        UIAlertAction *ok = [UIAlertAction actionWithTitle:@"同意" style:(UIAlertActionStyleDefault) handler:^(UIAlertAction * _Nonnull action) {
            completionHandler(YES);
        }];
        
        UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"不同意" style:(UIAlertActionStyleCancel) handler:^(UIAlertAction * _Nonnull action) {
            completionHandler(NO);
        }];
        
        [alert addAction:ok];
        [alert addAction:cancel];
        [self presentViewController:alert animated:YES completion:nil];
    
    */
    
    }
    
    // JavaScript调用prompt方法后回调的方法 prompt是js中的输入框 需要在block中把用户输入的信息传入
    /** 对应js的prompt方法
     webView中弹出输入框时调用, 两个按钮 和 一个输入框
    
     @param webView webView description
     @param prompt 提示信息
     @param defaultText 默认提示文本
     @param frame 可用于区分哪个窗口调用的
     @param completionHandler 输入框消失的时候调用, 回调给JS, 参数为输入的内容
     */
    
    -(void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void(^)(NSString * _Nullable))completionHandler{
    
        NSLog(@"%@",prompt);
    
        completionHandler(@"123");
    
    /*
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"请输入" message:prompt preferredStyle:(UIAlertControllerStyleAlert)];
    
        
        [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
            textField.placeholder = @"请输入";
        }];
        
        UIAlertAction *ok = [UIAlertAction actionWithTitle:@"确定" style:(UIAlertActionStyleDefault) handler:^(UIAlertAction * _Nonnull action) {
            
            UITextField *tf = [alert.textFields firstObject];
            
                    completionHandler(tf.text);
        }];
        
        UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"取消" style:(UIAlertActionStyleCancel) handler:^(UIAlertAction * _Nonnull action) {
                    completionHandler(defaultText);
        }];
        
        [alert addAction:ok];
        [alert addAction:cancel];
        [self presentViewController:alert animated:YES completion:nil];
    
    */
    
    }
    
    // 默认预览元素调用
    
    - (BOOL)webView:(WKWebView *)webView shouldPreviewElement:(WKPreviewElementInfo *)elementInfo {
    
        NSLog(@"-----默认预览元素调用");
    
        return YES;
    
    }
    
    // 返回一个视图控制器将导致视图控制器被显示为一个预览。返回nil将WebKit的默认预览的行为。
    
    - (nullable UIViewController *)webView:(WKWebView *)webView previewingViewControllerForElement:(WKPreviewElementInfo *)elementInfo defaultActions:(NSArray> *)previewActions {
    
        NSLog(@"----返回一个视图控制器将导致视图控制器被显示为一个预览。返回nil将WebKit的默认预览的行为。");
    
        return self;
    
    }
    
    // 允许应用程序向它创建的视图控制器弹出
    
    - (void)webView:(WKWebView *)webView commitPreviewingViewController:(UIViewController *)previewingViewController {
    
        NSLog(@"----允许应用程序向它创建的视图控制器弹出");
    
    }
    
    // 显示一个文件上传面板。completionhandler完成处理程序调用后打开面板已被撤销。通过选择的网址,如果用户选择确定,否则为零。如果不实现此方法,Web视图将表现为如果用户选择了取消按钮。
    
    - (void)webView:(WKWebView *)webView runOpenPanelWithParameters:(WKOpenPanelParameters *)parameters initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void(^)(NSArray * _Nullable URLs))completionHandler {
    
        NSLog(@"----显示一个文件上传面板");
    
    }
    
    

    创建新的webView时调用的方法

    - (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {
    
        NSLog(@"-----创建新的webView时调用的方法");
    
        return webView;
    
    }
    

    关闭webView时调用的方法

    - (void)webViewDidClose:(WKWebView *)webView {
    
        NSLog(@"----关闭webView时调用的方法");
    
    }
    
    WKUserScript

    WKUserScript用于往加载的页面中添加额外需要执行的JavaScript代码, 主要是一个初始化方法:

    /*
    source: 需要执行的JavaScript代码
    injectionTime: 加入的位置, 是一个枚举
    typedef NS_ENUM(NSInteger, WKUserScriptInjectionTime) {
        WKUserScriptInjectionTimeAtDocumentStart,
        WKUserScriptInjectionTimeAtDocumentEnd
    } API_AVAILABLE(macosx(10.10), ios(8.0));
    
    forMainFrameOnly: 是加入所有框架, 还是只加入主框架
    */
    - (instancetype)initWithSource:(NSString *)source injectionTime:(WKUserScriptInjectionTime)injectionTime forMainFrameOnly:(BOOL)forMainFrameOnly;
    
    // 通过WKUserScript注入需要执行的JavaScript代码
    - (void)addUserScript:(WKUserScript *)userScript;
    // 移除所有注入的JavaScript代码
    - (void)removeAllUserScripts;
    
    
    WKWebsiteDataStore

    iOS7.0只有UIWebView, 而iOS8.0是有WKWebView, 但8.0的WKWebView没有删除缓存方法。iOS9.0之后就开始支持啦。
    所以使用时候一定要适配iOS9.0以上

    WKWebsiteDataStore 提供了网站所能使用的数据类型,包括 cookies,硬盘缓存,内存缓存活在一些WebSQL的数据持久化和本地持久化。可通过 WKWebViewConfiguration类的属性 websiteDataStore 进行相关的设置。WKWebsiteDataStore 相关的API也比较简单:

    // 默认的data store
    + (WKWebsiteDataStore *)defaultDataStore;
    
    // 如果为webView设置了这个data Store,则不会有数据缓存被写入文件
    // 当需要实现隐私浏览的时候,可使用这个
    + (WKWebsiteDataStore *)nonPersistentDataStore;
    
    // 是否是可缓存数据的,只读
    @property (nonatomic, readonly, getter=isPersistent) BOOL persistent;
    
    // 获取所有可使用的数据类型
    + (NSSet<NSString *> *)allWebsiteDataTypes;
    
    // 查找指定类型的缓存数据
    // 回调的值是WKWebsiteDataRecord的集合
    - (void)fetchDataRecordsOfTypes:(NSSet<NSString *> *)dataTypes completionHandler:(void (^)(NSArray<WKWebsiteDataRecord *> *))completionHandler;
    
    // 删除指定的纪录
    // 这里的参数是通过上面的方法查找到的WKWebsiteDataRecord实例获取的
    - (void)removeDataOfTypes:(NSSet<NSString *> *)dataTypes forDataRecords:(NSArray<WKWebsiteDataRecord *> *)dataRecords completionHandler:(void (^)(void))completionHandler;
    
    // 删除某时间后修改的某类型的数据
    - (void)removeDataOfTypes:(NSSet<NSString *> *)websiteDataTypes modifiedSince:(NSDate *)date completionHandler:(void (^)(void))completionHandler;
    
    // 保存的HTTP cookies
    @property (nonatomic, readonly) WKHTTPCookieStore *httpCookieStore
    
    
    dataTyle
    // 硬盘缓存
    WKWebsiteDataTypeDiskCache,
    
    // HTML离线web应用程序缓存
    WKWebsiteDataTypeOfflineWebApplicationCache,
    
    // 内存缓存
    WKWebsiteDataTypeMemoryCache,
    
    // 本地缓存
    WKWebsiteDataTypeLocalStorage,
    
    // cookies
    WKWebsiteDataTypeCookies,
    
    // HTML会话存储
    WKWebsiteDataTypeSessionStorage,
    
    //  IndexedDB 数据库
    WKWebsiteDataTypeIndexedDBDatabases,
    
    // WebSQL 数据库
    WKWebsiteDataTypeWebSQLDatabases
    
    
    WKWebsiteDataRecord
    // 展示名称, 通常是域名
    @property (nonatomic, readonly, copy) NSString *displayName;
    
    // 包含的数据类型
    @property (nonatomic, readonly, copy) NSSet<NSString *> *dataTypes;
    
    
    简单应用

    删除指定时间的所有类型数据
    例:删除所有

    NSSet *websiteDataTypes = [WKWebsiteDataStore allWebsiteDataTypes];
        NSDate *dateFrom = [NSDate dateWithTimeIntervalSince1970:0];
        [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:websiteDataTypes modifiedSince:dateFrom completionHandler:^{
            // Done
            NSLog(@"释放");
        }];
    
    

    查找删除

    WKWebsiteDataStore *dataStore = [WKWebsiteDataStore defaultDataStore];
        [dataStore fetchDataRecordsOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] completionHandler:^(NSArray<WKWebsiteDataRecord *> * _Nonnull records) {
            for (WKWebsiteDataRecord *record in records) {
                [dataStore removeDataOfTypes:record.dataTypes forDataRecords:@[record] completionHandler:^{
                    // done
                }];
            }
        }];
    
    

    查找删除特定的内容

    WKWebsiteDataStore *dataStore = [WKWebsiteDataStore defaultDataStore];
        [dataStore fetchDataRecordsOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] completionHandler:^(NSArray<WKWebsiteDataRecord *> * _Nonnull records) {
            for (WKWebsiteDataRecord *record in records) {
                if ([record.displayName isEqualToString:@"baidu"]) {
                    [dataStore removeDataOfTypes:record.dataTypes forDataRecords:@[record] completionHandler:^{
                        // done
                    }];
                }
            }
        }];
    

    因URL中含有中文加载网页白屏显示的解决方法就是将中文符号UTF8转码。
    看需要有时可以对url进行两次UTF8编码,第一次编码,中文会被转码成16进制,但是每个字符前面会有一个%号,这个%号会被看成转义字符影响浏览器的解析,所以还需要再编码一次。

    [@"中文" stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
    

    获取h5中的标题 添加进度条

    获取h5中的标题和添加进度条放到一起展示看起来更明朗一点,在初始化wenview时,添加两个观察者分别用来监听webview 的estimatedProgress和title属性:

    webview.navigationDelegate = self;
    webview.UIDelegate = self;
         
    [webview addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
    [webview addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:NULL];
    
    @property (nonatomic,weak) CALayer *progressLayer;
    
    -(void)setupProgress{
        UIView *progress = [[UIView alloc]init];
        progress.frame = CGRectMake(0, 0, KScreenWidth, 3);
        progress.backgroundColor = [UIColor  clearColor];
        [self.view addSubview:progress];
         
        CALayer *layer = [CALayer layer];
        layer.frame = CGRectMake(0, 0, 0, 3);
        layer.backgroundColor = [UIColor greenColor].CGColor;
        [progress.layer addSublayer:layer];
        self.progressLayer = layer;
    }
    

    实现观察者的回调方法:

    #pragma mark - KVO回馈
    -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<nskeyvaluechangekey,id> *)change context:(void *)context{
        if ([keyPath isEqualToString:@"estimatedProgress"]) {
            self.progressLayer.opacity = 1;
            if ([change[@"new"] floatValue] <[change[@"old"] floatValue]) {
                return;
            }
            self.progressLayer.frame = CGRectMake(0, 0, KScreenWidth*[change[@"new"] floatValue], 3);
            if ([change[@"new"]floatValue] == 1.0) {
                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                    self.progressLayer.opacity = 0;
                    self.progressLayer.frame = CGRectMake(0, 0, 0, 3);
                });
            }
        }else if ([keyPath isEqualToString:@"title"]){
            self.title = change[@"new"];
        }
    }
    

    本文参考链接来自:https://www.jianshu.com/p/833448c30d70http://www.cocoachina.com/ios/20180314/22589.html

    相关文章

      网友评论

        本文标题:iOS 加载WKWebView

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