欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

[iOS]WKWebView的使用

程序员文章站 2022-03-20 17:00:33
...

demo:https://download.csdn.net/download/u012881779/10928927
使用WKWebView加载H5,并与之进行一些交互。
[GABaseWKWebView]

#import "GABaseWKWebView.h"

@implementation GABaseWKWebView

- (instancetype)init {
    self = [super init];
    if (self) {
        [self setUserAgentInfo];
    }
    return self;
}

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self setUserAgentInfo];
    }
    return self;
}

- (instancetype)initWithFrame:(CGRect)frame configuration:(nonnull WKWebViewConfiguration *)configuration {
    self = [super initWithFrame:frame configuration:configuration];
    if (self) {
        [self setUserAgentInfo];
    }
    return self;
}

- (void)setUserAgentInfo {
    // userAgent设置
    [self evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id result, NSError *error) {
        NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
        NSString *appVer = [infoDictionary objectForKey:@"CFBundleShortVersionString"];
        NSString *oldAgent = result;
        NSString *newAgent;
        // 给User-Agent添加额外的信息 - 区分来自哪个app
        if ([oldAgent containsString:@"appmark"]) {
            newAgent = oldAgent;
        } else {
            newAgent = [NSString stringWithFormat:@"%@;AppInfo:appName=%@&&appVer=%@", oldAgent, @"appmark", appVer];
        }
        // 设置global User-Agent
        if (@available(iOS 9.0, *)) {
            [self setCustomUserAgent:newAgent];
        }
    }];
}

@end

[GABaseWKWebViewController]

#import "GABaseWKWebViewController.h"
#import <WebKit/WebKit.h>
#import "GABaseWKWebView.h"

@interface GABaseWKWebViewController () <WKNavigationDelegate, WKScriptMessageHandler>

@property (strong, nonatomic) GABaseWKWebView *webView;
@property (strong, nonatomic) NSArray *nameMArr;
@property (nonatomic, strong) NSString *loadUrl;

@end

@implementation GABaseWKWebViewController

- (void)dealloc {
    _loadUrl = nil;
    _webView = nil;
    _nameMArr = nil;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    if (!_webView) {
        _webView = [[GABaseWKWebView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
        _webView.navigationDelegate = self;
    }
    [self.view addSubview:_webView];
    
    /*
     链接不支持https协议时,需要去Info.plist设置允许任意加载
     App Transport Security Settings
        Allow Arbitrary Loads           YES
     */
    NSURL *pathUrl = [self handleLoadUrl:_loadUrl];
    [_webView loadRequest:[NSURLRequest requestWithURL:pathUrl]];
}

- (NSURL *)handleLoadUrl:(NSString *)urlString {
    // 处理url带有中文的
    NSString *encodedString = (NSString*) CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)urlString,(CFStringRef)@"!$&'()*+,-./:;[email protected]_~%#[]",NULL, kCFStringEncodingUTF8));
    NSURL *url = [NSURL URLWithString:encodedString];
    return url;
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self addScriptAction];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [self removeScriptAction];
}

// 注入JavaScript与原生交互协议
// JS 端可通过 window.webkit.messageHandlers.<name>.postMessage(<messageBody>) 发送消息
- (void)addScriptAction {
    if (!_nameMArr) {
        _nameMArr = [[NSArray alloc] initWithObjects:@"goHomeIos",@"sharePagesIos",@"getUserInfoIos",nil];
    }
    for (NSString *subName in _nameMArr) {
        [_webView.configuration.userContentController addScriptMessageHandler:self name:subName];
    }
}

// 移除注入的协议
- (void)removeScriptAction {
    if (_nameMArr) {
        for (NSString *subName in _nameMArr) {
            [_webView.configuration.userContentController removeScriptMessageHandlerForName:subName];
        }
    }
}

#pragma mark - WKNavigationDelegate

- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation {
    NSLog(@"开始加载");
}

- (void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation {
    NSLog(@"内容开始返回");
}

- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation {
    NSLog(@"加载完成");
}

- (void)webView:(WKWebView *)webView didFailLoadWithError:(nonnull NSError *)error {
    NSLog(@"加载失败 error : %@",error.description);
}

// 在发送请求之前,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    if (navigationAction.targetFrame == nil) {
        [webView loadRequest:navigationAction.request];
    }
    NSURL *URL = navigationAction.request.URL;
    NSString *urlPath = [URL absoluteString];
    NSString *scheme = [URL scheme];
    NSString *resourceSpecifier = [URL resourceSpecifier];
    
    if ([scheme isEqualToString:@"tel"]) {
        NSString *callPhone = [NSString stringWithFormat:@"telprompt://%@", resourceSpecifier];
        // 防止iOS 10及其之后,拨打电话系统弹出框延迟出现
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:callPhone]];
        });
        decisionHandler(WKNavigationActionPolicyCancel);
    } else if ([scheme isEqualToString:@"mqq"]) {
        if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"mqq://"]]) {
            NSString *callQQ = [NSString stringWithFormat:@"mqq://%@", resourceSpecifier];
            dispatch_async(dispatch_get_global_queue(0, 0), ^{
                [[UIApplication sharedApplication] openURL:[NSURL URLWithString:callQQ]];
            });
        }
        decisionHandler(WKNavigationActionPolicyCancel);
    } else if ([scheme isEqualToString:@"mailto"]) {
        NSString *callEmail = [NSString stringWithFormat:@"mailto://%@", resourceSpecifier];
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:callEmail]];
        });
        decisionHandler(WKNavigationActionPolicyCancel);
    } else {
        decisionHandler(WKNavigationActionPolicyAllow);
    }
}

// 在收到响应后,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {
    decisionHandler(WKNavigationResponsePolicyAllow);
}

#pragma mark - 执行JavaScript代码

- (void)loadJs:(NSString *)js {
    // ios11要求evaluateJavaScript主线程
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.webView evaluateJavaScript:js completionHandler:^(id _Nullable response, NSError * _Nullable error) {
            if (error) {
                NSLog(@"evaluateJavaScript error = %@\n", error);
            }
        }];
    });
}

#pragma mark - WKScriptMessageHandler
/*
 在协议方法中获取JavaScript端传递的事件和参数
 WKScriptMessage
    name    协议名称
    body    传递的参数
 */
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    NSLog(@"body:%@", message.body);
    NSLog(@"message.name = %@",message.name);
    NSString *name = message.name;
    if ([name isEqualToString:@"goHomeIos"]) {
        // 首页
    } else if ([name isEqualToString:@"sharePagesIos"]) {
        // 分享
    } else if ([message.name isEqualToString:@"getUserInfoIos"]) {
        // 获取用户信息
        [self getUsrInfo];
    }
}

- (void)getUsrInfo {
    NSString *usrId = @"UserID";
    NSString *token = @"Token";
    NSString *identity = @"Identity";
    NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:token,@"token", identity,@"identity", usrId,@"userId", nil];
    NSString *jsBody = [self dictionaryToJson:dic];
    NSString *js = [NSString stringWithFormat:@"javascript:vueObj.getUserInfoPage('%@')", jsBody];
    [self loadJs:js];
}

- (NSString *)dictionaryToJson:(NSDictionary *)dic {
    if (dic == nil) {
        return @"";
    }
    NSError *parseError = nil;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:&parseError];
    NSString *jsonStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    jsonStr = [jsonStr stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    jsonStr = [jsonStr stringByReplacingOccurrencesOfString:@" " withString:@""];
    jsonStr = [jsonStr stringByReplacingOccurrencesOfString:@"\\/" withString:@"/"];
    return jsonStr;
}

@end


TO:
[iOS]WKWebView的使用--API篇
iOS11.3 WKWebView清除cookie所踩的坑!

相关标签: WKWebView