美文网首页
ios 和JS的交互封装

ios 和JS的交互封装

作者: iOSZY | 来源:发表于2020-09-24 13:24 被阅读0次
    项目开发中常常会用到和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);

    }



相关文章

网友评论

      本文标题:ios 和JS的交互封装

      本文链接:https://www.haomeiwen.com/subject/wvvzyktx.html