项目开发中常常会用到和JS的交互,当交互频繁的时候,代码冗余量会很高,为了方便后期迭代和重构,简单的封装一下。
ZYWebViewModel.h
#import
#import "ZYCmdBaseMgr.h"
@interface ZYWebViewModel : NSObject
+ (NSString *)stitchPacametersWithBaseUrl:(NSString *)baseUrl;
/// 处理webView的baseUrl
/// @param path 路径,前面不用带”/“
+ (NSString *)handleBaseUrlWithPath:(NSString *)path;
/// 处理发过来的命令
+ (void)handleCommandModel:(ZYWebCmdModel*)cmdModel;
@end
ZYWebViewModel.m
#import "ZYWebViewModel.h"
#import "ZYProtocolEnvConfig.h"
#import "ZYClient.h"
#import "ZYWebViewCmdHandler.h"
@implementation ZYWebViewModel
+ (NSString *)stitchPacametersWithBaseUrl:(NSString *)baseUrl {
NSString*url = baseUrl;
ZYUserModel *user = [ZYClient shared].userManager.activedUser;
/// url的自定义
if([baseUrlrangeOfString:@"?"].location==NSNotFound) {
url = [NSString stringWithFormat:@"%@?userId=%@", url,kSafeString(user.userId)];
}else{
url = [NSString stringWithFormat:@"%@&userId=%@", url,kSafeString(user.userId)];
}
/// 自定义参数
NSMutableDictionary *paramDictionary = [NSMutableDictionary dictionary];
paramDictionary[@"&xxx"] = @"";
if(paramDictionary.allKeys.count>0) {
for(NSString*key in paramDictionary) {
url = [NSString stringWithFormat:@"%@%@=%@",url, key, paramDictionary[key]];
}
}
if ([ZYWebViewModel includeChineseWithUrl:url]) {
url = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)url, nil, nil, kCFStringEncodingUTF8));
}
return url;
}
+ (NSString *)handleBaseUrlWithPath:(NSString *)path {
NSString *originalUrl = @"https://www.baidu.com";
if (![EnvironmentConfigStr isEqualToString:@"release"]) {
originalUrl =@"https://www.baidu.com";
}
return[NSString stringWithFormat:@"%@/%@", originalUrl, path];
}
+ (void)handleCommandModel:(ZYWebCmdModel*)cmdModel {
NSDictionary*apiDict = [ZYWebViewModel commandApiDictionary];
NSDictionary*commandDict = [apiDict valueForKey:kSafeString(cmdModel.cmd)];
if(commandDict) {
NSString*name = [commandDict valueForKey:kWebCommandClassKey];
if(!isEmpty(name)) {
Classclass =NSClassFromString(name);
NSString*selStr = [commandDict valueForKey:kWebCommandSELKey];
sel Str = !isEmpty(selStr) ? selStr :@"responseCommandModel:";
// TODO:- 防止空或找不到
SEL selector =NSSelectorFromString(selStr);
if(selector) {
IMPimp = [class methodForSelector:selector];
id(*func)(id,SEL,ZYWebCmdModel*) = (void*)imp;
func(self, selector, cmdModel);
}else{
[ZYWebViewModel handleNoCommand:cmdModel];
}
}
}else{
[ZYWebViewModelhandleNoCommand:cmdModel];
}
}
+ (BOOL)includeChineseWithUrl:(NSString *)url {
for(inti =0; i < [urllength]; i++) {
inta = [urlcharacterAtIndex:i];
if( a >0x4e00&& a <0x9fff) {
returnYES;
}
}
return NO;
}
+ (NSDictionary *)commandApiDictionary {
return [ZYWebViewCmdHandler getAllWebViewCmdsDictionary];
}
+ (void)handleNoCommand: (ZYWebCmdModel*)cmdModel {
[ZYCmdBaseMgr handleFailure:@{@"status" : @"404",
@"data" : cmdModel.cmd}
commandModel:cmdModel];
// if (![EnvironmentConfigStr isEqualToString:@"app_store"] &&
// ![EnvironmentConfigStr isEqualToString:@"test_flight"] &&
// ![EnvironmentConfigStr isEqualToString:@"ad_hoc"]) { // 测试环境
// [[UIApplication sharedApplication].keyWindow makeToastWith:[NSString stringWithFormat:@"--> %@\n该命令未定义或未找到,请开发人员自查~", cmdModel.cmd]];
// }
}
@end
ZYCmdBaseMgr.h
#import <Foundation/Foundation.h>
#import <UIkit/UIkit.h>
#import <WebKit/WebKit.h>
#import <MJExtension.h>
@class ZYWebCmdModel;
@interface ZYCmdBaseMgr : NSObject
/// 响应命令
+ (void)responseCommandModel:(ZYWebCmdModel *)model;
/// 向H5传递成功的回调
/// @param data 回调数据
+ (void)handleSuccessData:(id)data
commandModel:(ZYWebCmdModel*)model;
/// 向H5传递成功的回调
/// @param data 回调数据
/// @param param 额外添加的数据参数
+ (void)handleSuccessData:(id)data
addParamters:(NSDictionary*)param
commandModel:(ZYWebCmdModel*)model;
/// 向H5传递失败的回调
/// @param dataDict 回调数据
+ (void)handleFailure:(NSDictionary*)dataDict
commandModel:(ZYWebCmdModel*)model;
/// 向H5传递自定义数据的回调
/// @param dataDict 回调数据
+ (void)handleCustomParamters:(NSDictionary *)dataDict
commandModel:(ZYWebCmdModel*)model;
/// 直接传值给H5
/// @param paramStr json字符串
+ (void)sendOnlyStringDataToWebView:(NSString *)paramStr
cmdModel:(ZYWebCmdModel*)model;
@end
@interface ZYWebCmdModel : NSObject
// -------- decidePolicy参数 --------
@property (nonatomic, copy) NSString *cmd; /// 命令
@property (nonatomic, strong) id args; /// 参数 太坑,有时候是json字符串,有时候是字典对象
@property (nonatomic, copy) NSString *callbackId; /// 回调ID
// -------- 自定义参数 --------
@property (nonatomic, strong) UIViewController __kindof *currentCtrl; /// 当前控制器
@property(nonatomic,strong)WKWebView *webView; ///当前webView
@property(nonatomic,copy) NSString*originalStr; ///原始数据
/// 把H5传过来的 Absolute String 模型化
/// @param h5AbsoluteStr Absolute String
+ (instancetype)commandModel: (NSString*)h5AbsoluteStr;
@end
ZYCmdBaseMgr.m
#import "ZYCmdBaseMgr.h"
@implementation ZYCmdBaseMgr
+ (void)responseCommandModel:(ZYWebCmdModel *)model {
// 子类重写
}
+ (void)handleSuccessData:(id)data
commandModel:(ZYWebCmdModel*)model {
NSDictionary*dict =@{
@"data" : data,
@"status" : @"0"
};
[ZYCmdBaseMgr sendDataToWebView:dict
cmdModel:model];
}
+ (void)handleSuccessData:(id)data
addParamters:(NSDictionary*)param
commandModel:(ZYWebCmdModel*)model {
NSMutableDictionary *dictM = [[NSMutableDictionary alloc] initWithDictionary:param];
[dict MsetValue:dataforKey:@"data"];
[dict MsetValue:@"0"forKey:@"status"];
[ZYCmdBaseMgr sendDataToWebView:dictM
cmdModel:model];
}
+ (void)handleFailure:(NSDictionary*)dataDict
commandModel:(ZYWebCmdModel*)model {
[ZYCmdBaseMgr sendDataToWebView:dataDict
cmdModel:model];
}
+ (void)handleCustomParamters:(NSDictionary *)dataDict commandModel:(ZYWebCmdModel *)model {
[ZYCmdBaseMgr sendDataToWebView:dataDict
cmdModel:model];
}
+ (void)sendDataToWebView:(NSDictionary*)parmaDict
cmdModel:(ZYWebCmdModel*)model {
NSError*error;
NSData *jsonData = [NSJSONSerializationd ataWithJSONObject:parmaDict
options:kNilOptions
error:&error];
NSString*jsonStr = [[NSString alloc]initWithData:jsonData
encoding:NSUTF8StringEncoding];
NSString*backStr = [NSStringstring WithFormat:@"%@('%@',%@)",
model.callbackId,
jsonStr];
NSLog(@"--backStr --- %@---",backStr);
[model.webViewevaluateJavaScript:backStr
completionHandler:^(id_Nullableobject,NSError*_Nullableerror) {
NSLog(@" 回调的结果- %@ -- %@ --- ",error,object);
}];
}
+ (void)sendOnlyStringDataToWebView:(NSString *)paramStr
cmdModel:(ZYWebCmdModel*)model {
NSString *backStr = [NSString stringWithFormat:@""];
[model.webView evaluateJavaScript:backStr
completionHandler:^(id _Nullable object, NSError * _Nullable error) {
NSLog(@" - %@ -- %@ --- ",error,object);
}];
}
@end
@implementation ZYWebCmdModel
//+ (NSDictionary *)modelContainerPropertyGenericClass {
// return @{
// @"args" : [NSDictionary class]
// };
//}
+ (instancetype)commandModel:(NSString*)h5AbsoluteStr {
NSString*jsonStr = [[h5AbsoluteStr componentsSeparatedByString:@"://?"]lastObject];
ZYWebCmdModel*model = [ZYWebCmdModel mj_objectWithKeyValues:jsonStr];
model.originalStr = jsonStr;
returnmodel;
}
@end
ZYWebViewCmdHandler.h
#import <Foundation/Foundation.h>
extern NSString *kWebCommandClassKey;
extern NSString *kWebCommandSELKey;
@interface ZYWebViewCmdHandler : NSObject
/// 获取所有定义命令
+ (NSDictionary *)getAllWebViewCmdsDictionary;
@end
ZYWebViewCmdHandler.m
#import "ZYWebViewCmdHandler.h"
@interface ZYWebViewCmdHandler()
@property (nonatomic, copy) NSDictionary *cmdDict;
@end
NSString *kWebCommandClassKey = @"ZYWebViewCmdHandlerCommandClassKey";
NSString *kWebCommandSELKey =@"ZYWebViewCmdHandlerCommandSELKey";
@implementation ZYWebViewCmdHandler
+ (NSDictionary *)getAllWebViewCmdsDictionary {
return [[ZYWebViewCmdHandler alloc] init].cmdDict;
}
- (NSDictionary *)cmdDict {
if(!_cmdDict) {
_cmdDict=@{
/* 打开url */
/* key为class Value为selector */
@"openUrl":@{
kWebCommandClassKey:@"ZYWebCommonMgr",
kWebCommandSELKey :@"openUrl:"
},
};
}
return _cmdDict;
}
@end
ZYProtocolEnvConfig.h
#import <Foundation/Foundation.h>
typedefNS_ENUM(NSInteger,ZYEnvironment) {
ZYEnvironmentDevelop =0,
ZYEnvironmentProduct =1,
};
typedefenum: NSUInteger {
ZYBaseURLTypeUserCenter,
ZYBaseURLTypeCustom,
ZYBaseURLTypeWechat
} ZYBaseURLType;
typedefNS_ENUM(NSInteger,ZYRequestMethod) {
ZYRequestMethodGET,
ZYRequestMethodPOST,
ZYRequestMethodDELETE,
};
@interface ZYProtocolEnvConfig : NSObject
+ (NSString *)baseUrlWithType:(ZYBaseURLType)type;
@end
ZYProtocolEnvConfig.m
#import "ZYProtocolEnvConfig.h"
@implementation ZYProtocolEnvConfig
+ (NSString*)baseUrlWithType:(ZYBaseURLType)type {
switch ([ZYProtocolEnvConfig currentEnvironment]) {
case ZYEnvironmentProduct: {
switch(type) {
case ZYBaseURLTypeUserCenter:
return @"https://www.release.com";
break;
case ZYBaseURLTypeWechat:
return @"wxApiRelease";
break;
default:
break;
}
}
break;
case ZYEnvironmentDevelop: {
switch(type) {
case ZYBaseURLTypeUserCenter:
return @"https://www.developer.com";
break;
case ZYBaseURLTypeWechat:
return @"wxApiDeveloper";
break;
default:
break;
}
}
break;
default:
break;
}
if (type == ZYBaseURLTypeCustom) {
return@"";
}
/// 添加在头文件的自定义log宏
DDLogError(@"[Protocol] Base url is invalid. Please contact root with log.");
return @"Please contact root with log";
}
+ (ZYEnvironment)currentEnvironment {
/// 获取plist文件中EnvironmentConfig的值,该值为release和debug,为当前环境
/// [[[NSBundle mainBundle] infoDictionary] objectForKey:@"EnvironmentConfig"];
if ([EnvironmentConfigStr isEqualToString:@"release"]) {
return ZYEnvironmentProduct;
}else{
return ZYEnvironmentDevelop;
}
}
@end
具体使用
decidePolicyForNavigationAction方法中拦截后
在ZYWebViewCmdHandler中 添加对应的keyValue 然后根据class来实现对应selector
// 拦截h5请求体
NSString*requestString = [ZYCommonManager URLDecodedString:navigationAction.request.URL.absoluteString];
self.targetUrl = requestString;
// 判断请求体
if([requestStringhasPrefix:@"xxxx://"]) {
ZYWebCmdModel*model = [ZYWebCmdModel commandModel:requestString];
model.webView = webView;
model.currentCtrl=self;
[ZYWebViewModel handleCommandModel:model];
// 拦截跳转
decisionHandler(WKNavigationActionPolicyCancel);
}else{
// 继续跳转
decisionHandler(WKNavigationActionPolicyAllow);
}







网友评论