Files
yinmeng-ios/xplan-ios/Main/XPWebViewController.m
2021-12-02 20:33:26 +08:00

418 lines
18 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 "XPShareView.h"
#import "TTPopup.h"
#import "XPMacro.h"
#import <Masonry/Masonry.h>
#import <MJExtension/MJExtension.h>
#import <RPSDK/RPSDK.h>
typedef NS_ENUM(NSUInteger, RightNavigationPushType){
///跳转h5页面
RightNavigationPushType_Web = 1,
///分享
RightNavigationPushType_Share = 2,
///跳转原生页面
RightNavigationPushType_AppPage = 3,
///分享图片
RightNavigationPushType_SharePicture = 5
};
@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;
///分享的内容
@property (nonatomic,copy) NSDictionary *shareDic;
@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";
NSString * const kJSInitNav = @"initNav";
@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]) {
if (message.body && message.body != [NSNull null]) {
NSDictionary *body;
//不知道是哪个蓝精灵弄的变成了个dic所以我们要判断类型
if ([message.body isKindOfClass:[NSDictionary class]]) {
body = message.body;
} else if ([message.body isKindOfClass:[NSString class]]) {
body = [message.body toJSONObject];
}
self.shareDic = body[@"data"];
[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
} else if([message.name isEqualToString:kJSInitNav]) {
[self initNav:message.body];
}
}
}];
}
- (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];
}
}
#pragma mark - 分享
- (void)initNav:(NSDictionary *)response{
if(!response || ![response isKindOfClass:[NSDictionary class]])return;
self.shareDic = response[@"data"];
if ([response[@"type"] intValue]== RightNavigationPushType_Web) {
[self addNavigationItemWithTitles:@[response[@"data"][@"title"]] titleColor:[ThemeColor alertTitleColor] isLeft:NO target:self action:@selector(gotoWebView) tags:nil];
}else if ([response[@"type"] intValue]== RightNavigationPushType_Share || [response[@"type"] intValue]== RightNavigationPushType_SharePicture){
[self addNavigationItemWithImageNames:@[@"family_person_share"] isLeft:NO
target:self action:@selector(showSharePanel) tags:nil];
}
}
- (void)gotoWebView {
if (self.shareDic[@"link"]) {
XPWebViewController * webVC = [[XPWebViewController alloc] init];
webVC.url = self.shareDic[@"link"];
[self.navigationController pushViewController:webVC animated:YES];
}
}
- (void)showSharePanel {
if (self.shareDic.allKeys.count <= 0) {
return;
}
NSDictionary * dic = self.shareDic;
XPShareInfoModel * shareInfo = [[XPShareInfoModel alloc] init];
shareInfo.shareTitle = self.shareDic[@"title"];
shareInfo.shareContent = dic[@"desc"];
shareInfo.shareImageUrl = dic[@"imgUrl"];
shareInfo.type = ShareType_H5;
NSString *urlStr = ((NSString *)dic[@"url"]).length > 0 ? dic[@"url"] : dic[@"showUrl"];
if (urlStr.length) {
if ([urlStr containsString:@"?"]) {
urlStr = [NSString stringWithFormat:@"%@&shareUid=%@",urlStr,[AccountInfoStorage instance].getUid];
} else {
urlStr = [NSString stringWithFormat:@"%@?shareUid=%@",urlStr,[AccountInfoStorage instance].getUid];
}
}
shareInfo.shareUrl = urlStr;
XPShareItem *cycle = [XPShareItem itemWitTag:XPShareItemTagMoments title:@"朋友圈" imageName:@"share_wechat_circle_normal" disableImageName:@"share_wechat_circle_disable"];
XPShareItem *wechat = [XPShareItem itemWitTag:XPShareItemTagWeChat title:@"微信好友" imageName:@"share_wechat_normal" disableImageName:@"share_wechat_disable"];
XPShareItem *qq = [XPShareItem itemWitTag:XPShareItemTagQQ title:@"QQ好友" imageName:@"share_qq_normal" disableImageName:@"share_qq_disable"];
XPShareItem *qqzone = [XPShareItem itemWitTag:XPShareItemTagQQZone title:@"QQ空间" imageName:@"share_qqzone_normal" disableImageName:@"share_qqzone_disable"];
NSArray * items = @[wechat,cycle, qq, qqzone];
CGFloat margin = 15;
CGSize itemSize = CGSizeMake((KScreenWidth-2*margin)/4, 65);
XPShareView *shareView = [[XPShareView alloc] initWithItems:items itemSize:itemSize shareInfo:shareInfo];
shareView.delegate = self;
[TTPopup popupView:shareView style:TTPopupStyleActionSheet];
}
#pragma mark - XCShareViewDelegate
- (void)shareViewDidClickCancle:(XPShareView *)shareView {
[TTPopup dismiss];
}
- (void)shareView:(XPShareView *)shareView didSuccess:(XPShareInfoModel *)shareInfo {
[TTPopup dismiss];
NSMutableDictionary *params = [NSMutableDictionary dictionary];
NSString *uid = [AccountInfoStorage instance].getUid;
NSString *ticket = [AccountInfoStorage instance].getTicket;
[params setObject:uid forKey:@"uid"];
[params setObject:@(shareInfo.shareType) forKey:@"shareType"];
[params setObject:ticket forKey:@"ticket"];
[params setObject:@(shareInfo.type) forKey:@"sharePageId"];
if (shareInfo.shareUrl.length > 0) {
[params setObject:shareInfo.shareUrl forKey:@"shareUrl"];
}
if (shareInfo.roomUid > 0) {
[params setObject:@(shareInfo.roomUid) forKey:@"targetUid"];
}
[HttpRequestHelper POST:@"usershare/save" params:params success:^(BaseModel * _Nonnull data) {
} failure:^(NSInteger resCode, NSString * _Nonnull message) {
}];
}
- (void)shareView:(XPShareView *)shareView shareFail:(NSString *)message {
[TTPopup dismiss];
[self showErrorToast:message];
}
- (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];
// 分享按钮
[_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kJSInitNav];
}
return _userContentController;
}
@end