自定义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 

@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 

#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 *)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代码添加到工程即可。

你可能感兴趣的:(自定义BeeHive Module)