iOS WKWebView的一些注意的点

不积跬步,无以至千里;不积小流,无以成江海


在现在混合开发的时代,纯原生越来越不现实,基本上每个app都会和h5有交集,熟悉原生和h5之间的交互,快速实现需求也是每个coder需要的必备技能。(本文的webView都是特指WKWebView)

一、先记录一些h5和iOS的交互,不涉及rn和flutter。h5和原生是通过js构建的桥梁

1、iOS通过js调用h5

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

webView提供了执行js的方法,我一般是在加载完html后执行一些js,比如获取页面高度

- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation{
    NSString *doc = @"document.body.outerHTML";
    [webView evaluateJavaScript:doc
                     completionHandler:^(id _Nullable htmlStr, NSError * _Nullable error) {
                         if (error) {
                             NSLog(@"JSError:%@",error);
                         }
                         NSLog(@"html:%@",htmlStr);
                     }] ;
}

2、h5通过js回调原生

iOS:需要在初始化webView配置configuration,给configuration添加相应的userContentController
说明:这里没有直接使用WKScriptMessageHandler而是自定义它的代理,直接使用是强引用,造成循环引用,这个页面就不能释放
下面以PayParam为例:

@interface WeakScriptMessageDelegate : NSObject<WKScriptMessageHandler>

@property (nonatomic, weak) id<WKScriptMessageHandler> scriptDelegate;

- (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate;

@end
@implementation WeakScriptMessageDelegate

- (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate
{
    self = [super init];
    if (self) {
        _scriptDelegate = scriptDelegate;
    }
    return self;
}

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
    [self.scriptDelegate userContentController:userContentController didReceiveScriptMessage:message];
}

webView初始化

 WKUserContentController *userContentController = [[WKUserContentController alloc] init];
    [userContentController addScriptMessageHandler:[[WeakScriptMessageDelegate alloc] initWithDelegate:self] name:@"PayParam"];
    cfg.userContentController = userContentController;
    
    WKWebView *webView = [[WKWebView alloc] initWithFrame:(CGRectMake(0, NavH, ScreenWidth, ScreenHeight-NavH)) configuration:cfg];

代理方法的处理

- (void)userContentController:(WKUserContentController *)userContentController
      didReceiveScriptMessage:(WKScriptMessage *)message {
    WS(ws)
    if ([message.name isEqualToString:@"PayParam"]) {
        //和h5约定好数据结构
        NSDictionary *params = message.body;
        //后面是相应的处理


    }
}

h5:h5这边的写法就比较简单了,只需要判断手机机型,如果是苹果手机就调用相应的方法就可以了window.webkit.messageHandlers.<对象名>.postMessage(<数据>)

window.webkit.messageHandlers.PayParam.postMessage({})

二、webView页面内部的点击跳转

webView页面内可以有很多的点击事件,但不是所有的事件都是可以识别的,下面列举几种我碰到过的

1、webView做推广页面时,希望从我们的webView能跳转到商店,或者跳转到推广app(企业包)的下载地址
2、webView有电话时,希望能点击弹出提示打电话
3、h5内部可能有scheme的链接跳转

代码如下:

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction 
decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
    NSURL *url = navigationAction.request.URL;
    NSString *scheme = [url scheme];
    UIApplication *app = [UIApplication sharedApplication];
    // 打电话
    if ([scheme isEqualToString:@"tel"]) {
        if ([app canOpenURL:url]) {
            [app openURL:url];
            // 一定要加上这句,否则会打开新页面
            decisionHandler(WKNavigationActionPolicyCancel);
            return;
        }
    }
    // 打开appstore
    if ([url.absoluteString containsString:@"itunes.apple.com"]) {
        if ([app canOpenURL:url]) {
            [app openURL:url];
            decisionHandler(WKNavigationActionPolicyCancel);
            return;
        }
    }
    //下载企业包
    if ([url.absoluteString containsString:@"itms-services://"]) {
        if (@available(iOS 10.0, *)) {
            [app openURL:url options:@{} completionHandler:^(BOOL success) {
                
            }];
        } else {
            [app openURL:url];
        }
        decisionHandler(WKNavigationActionPolicyCancel);
        return;
    }
    
    decisionHandler(WKNavigationActionPolicyAllow);
}

webView是否打开新的url是通过这个方法来判断的
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
如果是不合法url默认返回的是WKNavigationActionPolicyCancel,所以需要手动来处理

三、webView播放背景音乐默认没有声音

webView默认没有打开播放声音,需要手动打开

WKUserContentController *userContentController = [[WKUserContentController alloc] init];
        cfg.userContentController = userContentController;
        cfg.allowsInlineMediaPlayback = YES;
        if (@available(iOS 10.0, *)) {
            cfg.mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone;
        }else {
            cfg.mediaPlaybackRequiresUserAction = NO;
        }

这些是和h5交互遇到的一些问题,以后发现新的问题再补充~
git地址:https://github.com/famile/YXBaseVCTool


跑得慢,听到的是骂声; 跑得快,听到的就只是风声


转载于:https://www.jianshu.com/p/6bcdc1096806

猜你喜欢

转载自blog.csdn.net/weixin_34033624/article/details/91118316