Files
yinmeng-ios/xplan-ios/Main/XPWebViewController.m
2021-09-23 19:32:54 +08:00

353 lines
15 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// XPWebViewController.m
// xplan-ios
//
// Created by zu on 2021/9/16.
//
#import "XPWebViewController.h"
#import "AccountInfoStorage.h"
#import "ThemeColor.h"
#import "ApiHost.h"
#import "YYUtility.h"
#import "HttpRequestHelper.h"
#import "XCShareView.h"
#import "TTPopup.h"
#import "XPMacro.h"
#import <Masonry/Masonry.h>
#import <MJExtension/MJExtension.h>
#import <RPSDK/RPSDK.h>
@interface WeakWebViewScriptMessageDelegate : NSObject<WKScriptMessageHandler>
//WKScriptMessageHandler 这个协议类专门用来处理JavaScript调用原生OC的方法
@property (nonatomic, weak) id<WKScriptMessageHandler> scriptDelegate;
- (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate;
@end
@implementation WeakWebViewScriptMessageDelegate
- (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate {
self = [super init];
if (self) {
_scriptDelegate = scriptDelegate;
}
return self;
}
//遵循WKScriptMessageHandler协议必须实现如下方法然后把方法向外传递
//通过接收JS传出消息的name进行捕捉的回调方法
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
if ([self.scriptDelegate respondsToSelector:@selector(userContentController:didReceiveScriptMessage:)]) {
[self.scriptDelegate userContentController:userContentController didReceiveScriptMessage:message];
}
}
@end
@interface XPWebViewController () <WKNavigationDelegate, WKScriptMessageHandler, XCShareViewDelegate>
@property (strong, nonatomic) WKWebView *webview;
@property (strong, nonatomic) UIProgressView *progressView;
@property (nonatomic, strong) WKUserContentController *userContentController;
@end
NSString * const kJSOpenPurse = @"openPurse";
NSString * const kJSOpenChargePage = @"openChargePage";
NSString * const kJSOpenSharePage = @"openSharePage";
NSString * const kJSGetUid = @"getUid";
NSString * const kJSGetDeviceId = @"getDeviceId";
NSString * const kJSGetTicket = @"getTicket";
NSString * const kJSGetDeviceInfo = @"getDeviceInfo";
NSString * const kJSOpenFaceLiveness = @"openFaceLiveness";
@implementation XPWebViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self initView];
}
- (void)initView {
if (self.navigationController.viewControllers.count > 1){
UIBarButtonItem *leftBarButtonItem = [[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:@"common_nav_back"] style:UIBarButtonItemStylePlain target:self action:@selector(backButtonClick)];
leftBarButtonItem.tintColor = UIColor.whiteColor;
self.navigationItem.leftBarButtonItem = leftBarButtonItem;
}
self.automaticallyAdjustsScrollViewInsets = NO;
[self.view addSubview:self.webview];
[self.webview mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.top.bottom.mas_equalTo(self.view);
}];
[self.view addSubview:self.progressView];
}
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
[self.webview evaluateJavaScript:@"document.location.href" completionHandler:^(id _Nullable response, NSError * _Nullable error) {
NSLog(@"%@", response);
NSString *currentUrl = [NSString stringWithFormat:@"%@", response];
if (currentUrl != nil && [currentUrl containsString:API_HOST_URL]) {
if ([message.name isEqualToString:kJSOpenSharePage]) {
[self showSharePanel];
} else if ([message.name isEqualToString:kJSGetUid]) {
NSString *uid = [[AccountInfoStorage instance] getUid];
NSString *js = [NSString stringWithFormat:@"getMessage(\"uid\",%@)", uid];
[self.webview evaluateJavaScript:js completionHandler:^(id _Nullable other, NSError * _Nullable error) {
NSLog(@"%@",error);
}];
} else if ([message.name isEqualToString:kJSGetTicket]) {
NSString *ticket = [[AccountInfoStorage instance] getTicket];
NSString *js = [NSString stringWithFormat:@"getMessage(\"ticket\",\"%@\")",ticket];
[self.webview evaluateJavaScript:js completionHandler:^(id _Nullable other, NSError * _Nullable error) {
NSLog(@"%@",error);
}];
} else if ([message.name isEqualToString:kJSGetDeviceId]) {
NSString *js = [NSString stringWithFormat:@"getMessage(\"deviceId\",\"%@\")",[YYUtility deviceUniqueIdentification]];
[self.webview evaluateJavaScript:js completionHandler:^(id _Nullable other, NSError * _Nullable error) {
NSLog(@"%@",error);
}];
} else if ([message.name isEqualToString:kJSGetDeviceInfo]) {
NSDictionary *basicParmars = [HttpRequestHelper configBaseParmars:[[NSDictionary alloc] init]];
NSString *json = [basicParmars mj_JSONString];
NSString *js = [NSString stringWithFormat:@"getMessage(\"deviceInfo\",%@)", json];
[self.webview evaluateJavaScript:js completionHandler:^(id _Nullable ohter, NSError * _Nullable error) {
NSLog(@"%@", error);
}];
} else if ([message.name isEqualToString:kJSOpenPurse]) {
} else if ([message.name isEqualToString:kJSOpenChargePage]) {
} else if ([message.name isEqualToString:kJSOpenFaceLiveness]) {
NSString *verifyToken = message.body;
#if TARGET_OS_IPHONE
[RPSDK startWithVerifyToken:verifyToken viewController:self.navigationController completion:^(RPResult * _Nonnull auditState) {
NSString *jsStrUrl;
switch (auditState.state) {
case RPStatePass:
jsStrUrl = [NSString stringWithFormat:@"renderByStatus(\"%d\")", 2];
break;
case RPStateFail:
jsStrUrl = [NSString stringWithFormat:@"renderByStatus(\"%d\")", 1];
break;
case RPStateNotVerify:
jsStrUrl = [NSString stringWithFormat:@"renderByStatus(\"%d\")", -1];
break;
}
[self.webview evaluateJavaScript:jsStrUrl completionHandler:^(id _Nullable other, NSError * _Nullable error) {
NSLog(@"%@",error);
}];
}];
#endif
}
}
}];
}
- (void)setUrl:(NSString *)urlString{
_url = urlString;
if (_url == nil) {
return;
}
if (![_url hasPrefix:@"http"] && ![_url hasPrefix:@"https"]){
_url = [NSString stringWithFormat:@"%@/%@", API_HOST_URL, _url];
}
if (![_url containsString:@"?"]) {
_url = [NSString stringWithFormat:@"%@?platform=%@", _url, [YYUtility appName]];
} else {
_url = [NSString stringWithFormat:@"%@&platform=%@", _url, [YYUtility appName]];
}
// 去掉 urlString 中的空格。
NSString *noSpaceTextUrl = [_url stringByReplacingOccurrencesOfString:@" " withString:@""];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:noSpaceTextUrl]];
[self.webview loadRequest:request];
}
- (void)backButtonClick {
BOOL canGoBack = YES;
if (self.webview.backForwardList.backList.count <= 1) {
canGoBack = NO;
}
if ([self.webview canGoBack]) {
[self.webview goBack];
} else {
[self.navigationController popViewControllerAnimated:YES];
[self.userContentController removeAllUserScripts];
}
}
- (void)showSharePanel {
XCShareItem *cycle = [[XCShareItem alloc]init];
cycle.title = @"朋友圈";
cycle.imageName = @"share_wxcircle";
cycle.disableImageName = @"share_wxcircle_disable";
cycle.disable = NO;
cycle.itemTag = XCShareItemTagMoments;
XCShareItem *wfriend = [[XCShareItem alloc]init];
wfriend.title = @"微信好友";
wfriend.imageName = @"share_wx";
wfriend.disableImageName = @"share_wx_disable";
wfriend.disable = NO;
wfriend.itemTag = XCShareItemTagWeChat;
XCShareItem *zone = [[XCShareItem alloc]init];
zone.title = @"QQ空间";
zone.imageName = @"share_qqzone";
zone.disableImageName = @"share_qqzone_disable";
zone.disable = NO;
zone.itemTag = XCShareItemTagQQZone;
XCShareItem *qfriend = [[XCShareItem alloc]init];
qfriend.title = @"QQ好友";
qfriend.imageName = @"share_qq";
qfriend.disableImageName = @"share_qq_disable";
qfriend.disable = NO;
qfriend.itemTag = XCShareItemTagQQ;
CGFloat margin = 9;
CGSize itemSize = CGSizeMake((KScreenWidth-2*margin)/4, 111);
XCShareView *shareView = [[XCShareView alloc]initWithItemSize:itemSize items:@[cycle,wfriend,zone,qfriend] margin:margin];
shareView.delegate = self;
[TTPopup popupView:shareView style:TTPopupStyleActionSheet];
}
- (void)shareView:(XCShareView *)shareView didSelected:(XCShareItemTag)itemTag {
}
- (void)shareViewDidClickCancle:(XCShareView *)shareView {
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
if ([keyPath isEqualToString:@"estimatedProgress"]) {
self.progressView.progress = self.webview.estimatedProgress;
if (self.progressView.progress == 1) {
__weak typeof (self)weakSelf = self;
[UIView animateWithDuration:0.25f delay:0.3f options:UIViewAnimationOptionCurveEaseOut animations:^{
weakSelf.progressView.transform = CGAffineTransformMakeScale(1.0f, 1.0f);
} completion:^(BOOL finished) {
weakSelf.progressView.hidden = YES;
}];
}
} else if ([keyPath isEqualToString:@"title"]) {
if (object == self.webview) {
self.navigationItem.title = self.webview.title;
}else{
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
- (void)dealloc {
[self.webview removeObserver:self forKeyPath:@"estimatedProgress"];
[self.webview removeObserver:self forKeyPath:@"title"];
}
- (WKWebView *)webview {
if (_webview == nil) {
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc]init];
if (@available(iOS 10.0, *)) {
configuration.mediaTypesRequiringUserActionForPlayback = NO;
} else {
// Fallback on earlier versions
}
configuration.allowsInlineMediaPlayback = YES;
NSString *uid = [[AccountInfoStorage instance] getUid];
NSString *realCookie = [NSString stringWithFormat:@"%@=%@",@"uid",uid];
WKUserScript *cookieScript = [[WKUserScript alloc] initWithSource: [NSString stringWithFormat:@"document.cookie = '%@';", realCookie] injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
[self.userContentController addUserScript:cookieScript];
//根据生成的WKUserScript对象初始化WKWebViewConfiguration
configuration.preferences.javaScriptEnabled = YES;
configuration.preferences.javaScriptCanOpenWindowsAutomatically = YES;
configuration.preferences.minimumFontSize = 10;
configuration.selectionGranularity = WKSelectionGranularityCharacter;
configuration.userContentController = self.userContentController;
CGSize size = [UIScreen mainScreen].bounds.size;
_webview = [[WKWebView alloc]initWithFrame:CGRectMake(0, 0, size.width,size.height) configuration:configuration];
_webview.navigationDelegate = self;
//添加KVOWKWebView有一个属性estimatedProgress就是当前网页加载的进度所以监听这个属性
[_webview addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
//添加KVO监听title属性
[_webview addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:NULL];
UISwipeGestureRecognizer *swipeGesture = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(backButtonClick)];
[_webview addGestureRecognizer:swipeGesture];
[_webview.scrollView setShowsVerticalScrollIndicator:NO];
[_webview.scrollView setShowsHorizontalScrollIndicator:NO];
//set useragent
__weak typeof(self) weakSelf = self;
[_webview evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id result, NSError *error) {
NSString *userAgent = result;
if (![userAgent containsString:@"tutuAppIos erbanAppIos"]){
NSString *newUserAgent = [userAgent stringByAppendingString:@" tutuAppIos erbanAppIos"];
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:newUserAgent, @"UserAgent", nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:dictionary];
[[NSUserDefaults standardUserDefaults] synchronize];
[weakSelf.webview setCustomUserAgent:newUserAgent];
}
}];
}
return _webview;
}
- (UIProgressView *)progressView{
if (!_progressView) {
_progressView = [[UIProgressView alloc] initWithFrame:CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width, 1)];
_progressView.progressTintColor = [ThemeColor appMainColor];
_progressView.trackTintColor = [UIColor clearColor];
_progressView.transform = CGAffineTransformMakeScale(1.0f, 1.0f);
}
return _progressView;
}
- (WKUserContentController *)userContentController{
if (!_userContentController) {
//自定义的WKScriptMessageHandler 是为了解决内存不释放的问题
WeakWebViewScriptMessageDelegate *weakScriptMessageDelegate = [[WeakWebViewScriptMessageDelegate alloc] initWithDelegate:self];
_userContentController = [[WKUserContentController alloc] init];
// 分享面板
[_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSOpenSharePage];
// 钱包页面
[_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSOpenPurse];
// 充值页面
[_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSOpenChargePage];
// 获取uid
[_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSGetUid];
// 获取设备id
[_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSGetDeviceId];
// 获取Ticket
[_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSGetTicket];
// 获取设备info
[_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSGetDeviceInfo];
// 实人认证: 打开原生人脸认证
[_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSOpenFaceLiveness];
}
return _userContentController;
}
@end