zoukankan      html  css  js  c++  java
  • 使用objection来模块化开发iOS项目

    转自无网不剩的博客 

    objection 是一个轻量级的依赖注入框架,受Guice的启发,Google Wallet 也是使用的该项目。「依赖注入」是面向对象编程的一种设计模式,用来减少代码之间的耦合度。通常基于接口来实现,也就是说不需要new一个对象,而是通过相关的控制器来获取对象。2013年最火的PHP框架 laravel 就是其中的典型。

     
    假设有以下场景:ViewControllerA.view里有一个button,点击之后push一个ViewControllerB,最简单的写法类似这样:
    1. - (void)viewDidLoad 
    2.     [super viewDidLoad]; 
    3.     UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; 
    4.     button.frame = CGRectMake(100, 100, 100, 30); 
    5.     [button setTitle:@"Button" forState:UIControlStateNormal]; 
    6.     [button addTarget:self action:@selector(buttonTapped) forControlEvents:UIControlEventTouchUpInside]; 
    7.     [self.view addSubview:button]; 
    8.  
    9. - (void)buttonTapped 
    10.     ViewControllerB *vc = [[ViewControllerB alloc] init]; 
    11.     [self.navigationController pushViewController:vc animated:YES]; 
    这样写的一个问题是,ViewControllerA需要import ViewControllerB,也就是对ViewControllerB产生了依赖。依赖的东西越多,维护起来就越麻烦,也容易出现循环依赖的问题,而objection正好可以处理这些问题。
     
    实现方法是:先定义一个协议(protocol),然后通过objection来注册这个协议对应的class,需要的时候,可以获取该协议对应的object。对于使用方无需关心到底使用的是哪个Class,反正该有的方法、属性都有了(在协议中指定)。这样就去除了对某个特定Class的依赖。也就是通常所说的「面向接口编程」。
    1. JSObjectionInjector *injector = [JSObjection defaultInjector]; // [1] 
    2. UIViewController <ViewControllerAProtocol> *vc = [injector getObject:@protocol(ViewControllerAProtocol)]; // [2] 
    3. vc.backgroundColor = [UIColor lightGrayColor]; // [3] 
    4. UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:vc]; 
    5. self.window.rootViewController = nc; 
    [1] 获取默认的injector,这个injector已经注册过ViewControllerAProtocol了。
    [2] 获取ViewControllerAProtocol对应的Object。
    [3] 拿到VC后,设置它的某些属性,比如这里的backgroundColor,因为在ViewControllerAProtocol里有定义这个属性,所以不会有warning。
     
    可以看到这里没有引用ViewControllerA。再来看看这个ViewControllerAProtocol是如何注册到injector中的,这里涉及到了Module,对Protocol的注册都是在Module中完成的。Module只要继承JSObjectionModule这个Class即可。
    1. @interface ViewControllerAModule : JSObjectionModule 
    2. @end 
    3.  
    4. @implementation ViewControllerAModule 
    5. - (void)configure 
    6.     [self bindClass:[ViewControllerA class] toProtocol:@protocol(ViewControllerAProtocol)]; 
    7. @end 
     
    绑定操作是在configure方法里进行的,这个方法在被添加到injector里时会被自动触发。
    1. JSObjectionInjector *injector = [JSObjection defaultInjector]; // [1] 
    2. injector = injector ? : [JSObjection createInjector]; // [2] 
    3. injector = [injector withModule:[[ViewControllerAModule alloc] init]]; // [3] 
    4. [JSObjection setDefaultInjector:injector]; // [4] 
    [1] 获取默认的 injector
    [2] 如果默认的 injector 不存在,就新建一个
    [3] 往这个 injector 里注册我们的 Module
    [4] 设置该 injector 为默认的 injector
     
    这段代码可以直接放到 + (void)load里执行,这样就可以避免在AppDelegate里import各种Module。
     
    因为我们无法直接获得对应的Class,所以必须要在协议里定义好对外暴露的方法和属性,然后该Class也要实现该协议。
    1. @protocol ViewControllerAProtocol <NSObject> 
    2. @property (nonatomic) NSUInteger currentIndex; 
    3. @property (nonatomic) UIColor *backgroundColor; 
    4. @end 
    5.  
    6. @interface ViewControllerA : UIViewController <ViewControllerAProtocol> 
    7. @end 
     
    通过objection实现依赖注入后,就能更好地实现SRP(Single Responsibility Principle),代码更简洁,心情更舒畅,生活更美好。拿Pinterest来说,下面的页面就可以划分为3个Section。
     
    各个Section可以由不同的人负责,然后串到一起就行,也能一定程度地避免MVC(Mess View Controller)的出现。
     
    总体来说,这个lib还是挺靠谱的,已经维护了两年多,也有一些项目在用,对于提高开发成员的效率也会有不少的帮助,可以考虑尝试下。

    CocoaChina是全球最大的苹果开发中文社区,官方微信每日定时推送各种精彩的研发教程资源和工具,介绍app推广营销经验,最新企业招聘和外包信息,以及Cocos2d引擎、Cocos Studio开发工具包的最新动态及培训信息。关注微信可以第一时间了解最新产品和服务动态,微信在手,天下我有!

  • 相关阅读:
    Vue快速学习_第四节
    Vue快速学习_第三节
    Vue快速学习_第二节
    从N个元素的集合中随机取m个元素的算法实现
    Mysql加锁过程详解
    TFS 测试用例导入、导出工具
    TFS实现需求工作项自动级联保存
    Gulp自动构建Web前端程序
    Oracle PL/SQL Developer集成TFS进行团队脚本文件版本管理
    Python sphinx-build在Windows系统中生成Html文档
  • 原文地址:https://www.cnblogs.com/yulang314/p/5195857.html
Copyright © 2011-2022 走看看