美文网首页
WKWebView基本使用

WKWebView基本使用

作者: 辰牧殇 | 来源:发表于2017-04-27 16:16 被阅读209次

    为何使用WKWebView

    App开发过程中不可避免的会用到加载网页,从iOS2开始,我们一直使用的是UIWebView加载,这个网页加载器加载速度慢、占用内存多、优化困难,如果加载网页过多,还可能因为过度占用内存而被系统kill掉。

    iOS8以后,Apple推出了WebKit,提供了替换UIWebView的组件WKWebView,毫无疑问WKWebView将逐步取代笨重的UIWebView

    WKWebView新特性

    • 在性能、稳定性、功能方面有很大提升,网页加载速度快、内存占用少
    • 支持更多的HTML5特性
    • 与Safari相同的JavaScript引擎
    • 官方宣称的高达60fps的滚动刷新率以及内置手势
    • 增加加载进度属性:estimatedProgress
    • 将UIWebViewDelegate与UIWebView重构成了14类与3个协议(查看苹果官方文档);

    WKWebView使用说明

    初始化方法分两种(记得导入#import <WebKit/WebKit.h>

    // 默认初始化
    - (instancetype)initWithFrame:(CGRect)frame;
    
    // 根据对webview的相关配置,进行初始化
    - (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration NS_DESIGNATED_INITIALIZER;
    

    加载网页与HTML代码的方式与UIWebView相同

    WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds];
    
    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]]];
    
    [self.view addSubview:webView];
    

    网页导航刷新相关属性及方法

    // 是否可以后退
    @property (nonatomic, readonly) BOOL canGoBack;
    // 是否可以向前
    @property (nonatomic, readonly) BOOL canGoForward;
    // 是否正在加载
    @property (nonatomic, readonly) BOOL loading;
    // 加载进度,取值(0~1)
    @property (nonatomic, readonly) double estimatedProgress;
    // 是否允许左右划手势导航,默认不允许
    @property (nonatomic) BOOL allowsBackForwardNavigationGestures;
    // WKBackForwardList类型,访问历史列表,可以通过前进后退按钮访问,或者通过goToBackForwardListItem函数跳到指定页面
    @property (nonatomic, readonly, strong) WKBackForwardList *backForwardList;
    
    // 刷新
    - (WKNavigation *)reload;
    // 停止加载
    - (void)stopLoading;
    // 后退函数
    - (WKNavigation *)goBack;
    // 前进函数
    - (WKNavigation *)goForward;
    // 会比较网络数据是否有变化,没有变化则使用缓存,否则从新请求。
    - (WKNavigation *)reloadFromOrigin;
    // 跳转到某个指定历史页面
    - (WKNavigation *)goToBackForwardListItem:(WKBackForwardListItem *)item;
    

    WKWebView代理方法

    1.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 didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation;
    
    // 在收到响应后,决定是否跳转
    - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler;
    
    // 在发送请求之前,决定是否跳转
    - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;
    

    2.WKUIDelegate

    UI界面相关,原生控件支持,三种提示框:输入、确认、警告。首先将web提示框拦截然后再做处理。

    // 创建一个新的WebView
    - (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures;
    
    // 输入框
    - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler;
    
    // 确认框
    - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler;
    
    // 警告框
    - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler;
    

    3.WKScriptMessageHandler

    这个协议中包含一个必须实现的方法,这个方法是提高App与web端交互的关键,它可以直接将接收到的JS脚本转为OC或Swift对象。提供从网页中接收消息的回调方法。

    // 从web界面中接收到一个脚本时调用
    - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;
    

    小技巧

    • 自适应屏幕宽度
    NSString *jScript = @"var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);";
    
    WKUserScript *wkUScript = [[WKUserScript alloc] initWithSource:jScript injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
    
    WKUserContentController *wkUController = [[WKUserContentController alloc] init];
            
    [wkUController addUserScript:wkUScript];
            
    WKWebViewConfiguration *wkWebConfig = [[WKWebViewConfiguration alloc] init];
            
    wkWebConfig.userContentController = wkUController;
            
    _web1 = [[WKWebView alloc] initWithFrame:CGRectNull configuration:wkWebConfig];
    
    • 获取页面高度
    #pragma mark - WKNavigationDelegate
    - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
        [webView evaluateJavaScript:@"document.body.offsetHeight" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
            _webHeight = [result doubleValue];
        }];
    }
    
    • 图片自适应设备宽度
    NSString *js = @"function imgAutoFit() { \
    var imgs = document.getElementsByTagName('img'); \
    for (var i = 0; i < imgs.length; ++i) {\
    var img = imgs[i];   \
    img.style.maxWidth = %f;   \
    } \
    }";
    
    js = [NSString stringWithFormat:js, [UIScreen mainScreen].bounds.size.width - 20];
    
    WKUserScript *wkUScript = [[WKUserScript alloc] initWithSource:js injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
            
    WKUserContentController *wkUController = [[WKUserContentController alloc] init];
    
    [wkUController addUserScript:wkUScript];
    
    WKWebViewConfiguration *wkWebConfig = [[WKWebViewConfiguration alloc] init];
            wkWebConfig.userContentController = wkUController;
            
    _webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 64, qScreenWidth, qScreenHeight - 64) configuration:wkWebConfig];
    

    参考内容:

    使用WKWebView替换UIWebView

    UIWebView、WKWebView使用详解及性能分析

    WKWebView的使用和各种坑的解决方法(OC+Swift)

    相关文章

      网友评论

          本文标题:WKWebView基本使用

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