WKWebView的使用

来源:互联网 发布:源代码加密软件 编辑:程序博客网 时间:2024/06/07 11:37

iOS8.0之后苹果推出了新框架Webkit,提供了WKWebView的组件,用来替换UIWebView。之前UIWebView 加载速度慢,占用内存大,如果加载的网页比较多,占用内存比较大可能还会导致项目crash。WKWebView在性能上有了很大的优化,占用内存小,允许JavaScript的Nitro库加载并使用,支持了更多的HTML5特性。

WKWebView的使用
自定义一个WKWebVC

声明两个属性

@property (nonatomic,strong) WKWebView *webView;@property (nonatomic,copy) NSString *urlStr;

定义几个静态字符串 用来初始化注册js方法

static NSString * const JSHandlerNameShare = @"share";static NSString * const JSHandlerNameHideNavBar = @"hideNavBar";static NSString * const JSHandlerNameShowNavBar = @"showNavBar";static NSString * const JSHandlerNameSetNavBarAlpha = @"setNavBarAlpha";

初始化WKWebView

- (WKWebView *)webView {    if (!_webView) {        WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];        //允许html内联播放        config.allowsInlineMediaPlayback = YES;        _webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config];        _webView.backgroundColor = [UIColor whiteColor];        _webView.navigationDelegate = self;        _webView.UIDelegate = self;        _webView.scrollView.delegate = self;        //注册js方法        [_webView.configuration.userContentController addScriptMessageHandler:self name:JSHandlerNameShare];        [_webView.configuration.userContentController addScriptMessageHandler:self name:JSHandlerNameHideNavBar];        [_webView.configuration.userContentController addScriptMessageHandler:self name:JSHandlerNameSetNavBarAlpha];    }    return _webView;}

加载webView

- (void)setUrlStr:(NSString *)urlStr{    _urlStr = urlStr;    NSURL *url = [NSURL URLWithString:urlStr];    NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url cachePolicy:0 timeoutInterval:10.0];    [self.webView loadRequest:request];    [self.view addSubview:self.webView];}

遵守相应的代理协议并实现相应的代理方法

WKNavigationDelegate 代理方法如下:

- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{    //在此可以显示加载动画    NSLog(@"页面开始加载时调用");}- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{    //停止加载动画    NSLog(@"页面加载完毕");}- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error{    //页面加载失败,添加失败页面,或者是添加重新加载按钮    //重新加载需要重新赋值请求链接 重新loadRequest    NSLog(@"页面加载失败");}- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{    //内容返回后,加载动画停止    NSLog(@"当内容返回的时候调用");}

跳转前会调用以下这个方法,在跳转前可以进行判断跳转的链接,根据跟前端开发协商好的协议头和主机位判断是属于那种跳转,在这个方法中可以进行相应的操作。
- (void)webView:(WKWebView )webView decidePolicyForNavigationAction:(WKNavigationAction )navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;

声明一个通知 用于监听是属于那种跳转

extern NSString * const WKJumpNotification;

为该属性赋值

NSString * const WKJumpNotification = @"WKJumpNotification";

在viewDidLoad 中添加通知

- (void)viewDidLoad {    [super viewDidLoad];    self.view.backgroundColor = [UIColor whiteColor];    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(jumpAction:) name:WKJumpNotification object:nil];}

在请求链接跳转前进行如下监听

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{    //可以在此进行判断是属于那种跳转类型    //获取跳转链接    NSURL *url = navigationAction.request.URL;    //根据约定好的协议头进行判断    if ([url.scheme isEqualToString:@"saga"]) {        [[NSNotificationCenter defaultCenter] postNotificationName:WKJumpNotification object:nil userInfo:@{@"url":url}];        //不允许跳转        decisionHandler(WKNavigationActionPolicyCancel);    } else {        //允许页面跳转        decisionHandler(WKNavigationActionPolicyAllow);    }    NSLog(@"跳转前调用,决定是否跳转");}

定义一个枚举判断是属于那种跳转

typedef enum {    WKWebVCRequestTypeCustomerService = 1001,//客服列表    WKWebVCRequestTypeProductDetail = 1002,//商品详情    WKWebVCRequestTypeOrderDetail = 1003//订单详情}WKWebVCRequestType;

通知方法的执行

- (void)jumpAction:(NSNotification *)notification{    NSDictionary *dict = notification.userInfo;    id url = dict[@"url"];    if (![url isKindOfClass:[NSURL class]]) {        NSLog(@"参数不是请求URL");        return;    }    NSURL *requestUrl = url;    //根据主机位判断是属于那种跳转类型 这主机位事先跟web前端约定好    WKWebVCRequestType type = requestUrl.host.intValue;    switch (type) {        case WKWebVCRequestTypeCustomerService:            NSLog(@"跳转到客服列表");            break;        case WKWebVCRequestTypeProductDetail:            NSLog(@"跳转到商品详情");            break;        case WKWebVCRequestTypeOrderDetail:            NSLog(@"跳转到订单详情");            break;        default:            break;    }}

WKUIDelegate 的相应代理方法的使用 处理web界面的三种提示框(警告框、确认框、输入框)

//弹出提示框- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"温馨提示" message:message delegate:self cancelButtonTitle:@"确定" otherButtonTitles: nil];    [alertView show];    completionHandler();}//弹出确认框- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler {    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"确认框" message:message delegate:self cancelButtonTitle:@"取消" otherButtonTitles: @"确定",nil];    [alertView show];}//弹出输入框- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler {    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:prompt message:nil delegate:self cancelButtonTitle:@"取消" otherButtonTitles: @"确定",nil];    [alertView show];}

WKScriptMessageHandler 协议的使用,它能让网页通过JS把消息发送给OC

//网页通过JS把消息发送给OC- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{    //判断网页是进行那种操作    if ([message.name isEqualToString:JSHandlerNameShare]) { //分享        if ([message.body isKindOfClass:[NSDictionary class]]) {            //分享字典模型数据            NSDictionary *dict = message.body;        }        NSLog(@"在此可以弹出分享面板");    } else if ([message.name isEqualToString:JSHandlerNameHideNavBar]) {        NSLog(@"隐藏导航栏");    } else if ([message.name isEqualToString:JSHandlerNameShowNavBar]) {        NSLog(@"显示导航栏");    } else if ([message.name isEqualToString:JSHandlerNameSetNavBarAlpha]) {        if ([message.body isKindOfClass:[NSDictionary class]]) {            //根据模型字典中的数据设置导航栏的透明度            NSDictionary *dict = message.body;        }        NSLog(@"设置导航栏的透明度");    } else {        NSLog(@"没有注册此操作");    }}

在开发中使用WKWebView遇到一些问题

  • (void)dealloc;中发现self没有被释放,原因是注册的js事件没有移除

为了释放self 我在viewWillDisAppear里进行了如下操作

- (void)viewWillDisappear:(BOOL)animated{    //移除之前注册的js回调,不然会导致webView无法正常释放。    [self.webView.configuration.userContentController removeScriptMessageHandlerForName:JSHandlerNameShare];    [self.webView.configuration.userContentController removeScriptMessageHandlerForName:JSHandlerNameHideNavBar];    [self.webView.configuration.userContentController removeScriptMessageHandlerForName:JSHandlerNameShowNavBar];    [self.webView.configuration.userContentController removeScriptMessageHandlerForName:JSHandlerNameSetNavBarAlpha];}

由于webView指定了UIScrollViewDelegate,所以要在dealloc中将webView的滚动代理赋值为nil,否则会导致crash

- (void)dealloc{    //需要将滚动的代理赋值为nil否则会导致crash    _webView.scrollView.delegate = nil;    [[NSNotificationCenter defaultCenter] removeObserver:self];}

这是个人使用WKWebView的总结

0 0
原创粉丝点击