自定义BeeHive Module

背景

上次对BeeHive的一些基本原理进行了一定的分析,BeeHive提供的不仅仅是一个第三方库,其主张的模块化编程思想对解决日益庞大的代码有着借鉴意义。
BeeHive提供了对AppDelegate的封装,开发者如果需要在AppDelegate回调中调用方法,则需要实现相应的Module,Module声明了特定的接口,从代码规范方面来看,这是一种非常好的设计方式。开发者不需要在Appdelgate堆积大量代码,AppDelegate当中会依次调用相应的Module,Module之间做到了相互隔离。在开发应用框架时,这种设计非常有借鉴意义。例如设计某个流程逻辑,框架需要保证流程按顺序执行,其顺序是规定好的,开发人员不能随意改变。但开发人员可以在某些节点上嵌入特定的代码,根据中间结果执行相应的操作。比如像很多情况下,需要自定义WebViewController。WebViewController的正常逻辑是加载网页页面,但现在需要增加很多额外的功能,例如:网址白名单、Js bridge等。之前在实现时,将白名单跟Js bridge都写在一块,Js Bridge的功能非常多,每次增加新功能时,都需要在WebViewController文件增加新的功能代码。给到其它项目组用的时候,更新的时候非常麻烦。不能真正做到webview的插件化。看到BeeHive后,想尝试一下使用模块化的思想对webView进行一次封装。

设计

首先需要定义一个ModuleProtocol,这里只实现6个接口

@protocol BHWebViewModuleProtocol <NSObject>

@optional
- (void)viewDidLoad:(BHWebViewContext *)context;

- (BOOL)shouldStartLoadWithRequest:(BHWebViewContext *)context;

- (void)webViewDidStartLoad:(BHWebViewContext *)context;

- (void)webViewDidFinishLoad:(BHWebViewContext *)context;

- (void)didFailLoadWithError:(BHWebViewContext *)context;

+ (NSInteger)moduleLevel;

@end

定义了一个BHWebViewManager用于管理Manager,其中定义了注册Module方法

@interface BHWebViewManager : NSObject

+ (instancetype)sharedManager;

// 给BHWebViewController 注册Module
- (void)registerDynamicModule:(Class)moduleClass;

- (void)registedAnnotationModules;

- (id )tiggerEvent:(BHWebViewModuleEventType)eventType withContext:(BHWebViewContext *)context;

@end

自定义webViewController,BHWebViewContext用于传递运行参数

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    [self loadRequest:_request];
    BHWebViewContext *context = [[BHWebViewContext alloc] init];
    context.webViewController = self;
    [[BHWebViewManager sharedManager] tiggerEvent:BHviewDidLoad withContext:context];
    // Do any additional setup after loading the view.
}

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    BHWebViewContext *context = [[BHWebViewContext alloc] init];
    context.webViewController = self;
    context.webView = webView;
    context.request = request;
    context.navigationType = navigationType;
    id result = [[BHWebViewManager sharedManager] tiggerEvent:BHshouldStartLoadWithRequest withContext:context];
    return [result boolValue];
}

- (void)webViewDidStartLoad:(UIWebView *)webView
{
    BHWebViewContext *context = [[BHWebViewContext alloc] init];
    context.webViewController = self;
    context.webView = webView;
    [[BHWebViewManager sharedManager] tiggerEvent:BHwebViewDidStartLoad withContext:context];
}

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    BHWebViewContext *context = [[BHWebViewContext alloc] init];
    context.webViewController = self;
    context.webView = webView;
    [[BHWebViewManager sharedManager] tiggerEvent:BHwebViewDidFinishLoad withContext:context];
}

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
    BHWebViewContext *context = [[BHWebViewContext alloc] init];
    context.webViewController = self;
    context.webView = webView;
    [[BHWebViewManager sharedManager] tiggerEvent:BHdidFailLoadWithError withContext:context];
}

使用宏来注册Module,参数BHAnnotation来实现。

#import <Foundation/Foundation.h>

#ifndef BeehiveWebViewModSectName

#define BeehiveWebViewModSectName "BHWebViewMods"

#endif

#define BeeHiveWebViewDATA(sectname) __attribute((used, section("__DATA,"#sectname" ")))

#define BeeHiveWebViewMod(name) \
char * k##name##_mod BeeHiveWebViewDATA(BHWebViewMods) = ""#name"";

@interface BHWebViewAnnotation : NSObject

+ (NSArray<NSString *> *)AnnotationModules;

@end

自定义插件

白名单功能

BeeHiveWebViewMod(BHWebViewWhiteListModule)

@implementation BHWebViewWhiteListModule

- (BOOL)shouldStartLoadWithRequest:(BHWebViewContext *)context
{
    NSURLRequest *request = context.request;
    NSString *scheme = [[request URL] scheme];
    NSString *host = [[request URL] host];
    if ([scheme isEqualToString:@"https"] )
    {
        if([host isEqualToString:@"www.baidu.com"])
        {
            return YES;
        }
        else
        {
            return NO;
        }
    }
    return NO;
}

@end

js Bridge


BeeHiveWebViewMod(BHWebViewJsBridgeModule)

@implementation BHWebViewJsBridgeModule

- (BOOL)shouldStartLoadWithRequest:(BHWebViewContext *)context
{
    NSURLRequest *request = context.request;
    NSString *scheme = [[request URL] scheme];
    NSString *host = [[request URL] host];
    if ([scheme isEqualToString:@"exeJs"] )
    {
        if([host isEqualToString:@"showAlertView"])
        {
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"提示"
                                                                message:@"提示"
                                                               delegate:nil
                                                      cancelButtonTitle:@"确定"
                                                      otherButtonTitles: nil];
            [alertView show];
        }
    }
    return YES;
}

@end

通过借鉴BeeHive的设计,可以将webViewController实现Module化,白名单跟js Bridge可以实现插件化,通过宏来注册Module,在使用时,只需要将module代码添加到工程即可。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 174,002评论 25 709
  • WebSocket-Swift Starscream的使用 WebSocket 是 HTML5 一种新的协议。它实...
    香橙柚子阅读 24,173评论 8 184
  • 本人是一枚结构设计师,在设计院从事建筑结构设计工作。从业5年多,最近工作时时长想到一些设计中遇到的点,于是打算在简...
    MonoCookie阅读 188评论 0 0
  • 新司机上路 不得不说书是我的好朋友,我没有统计过我一年会读多少本书,只是一直在读,在读,遇到特别有感觉的书还会...
    李欣心理点滴阅读 509评论 0 1
  • “生活就是工作,劳动就是人的生活”。人的一生,都在劳动,劳动是人这一生生存的活动,不管脑力劳动还是体力劳动...
    河涨潮阅读 865评论 0 0