使用objection来模块化开发ios项目

2015-05-12 17:19:41 574浏览

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

 

    假设有以下场景:ViewControllerA的view里有一个button,点击之后push到ViewControllerB,最简单的写法类似这样:

 

Ios代码

1.    - (void)viewDidLoad {

2.    [super viewDidLoad];

3.     

4.    UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];

5.    button.frame = CGRectMake(100, 100, 100, 30);

6.    [button setTitle:@"PUSH" forState:UIControlStateNormal];

7.    [button addTarget:self action:@selector(buttonTapped) forControlEvents:UIControlEventTouchUpInside];

8.    [self.view addSubview:button];

9.    }

10.   

11.  - (void)buttonTapped {

12.  ViewControllerB *vc = [[ViewControllerB alloc] init];

13.  [self.navigationController pushViewController:vc animated:YES];

14.  }

复制代码

 

     这样写的一个问题是,ViewControllerA需要import ViewControllerB,也就是对ViewControllerB产生了依赖。依赖的东西越多,维护起来就越麻烦,也容易出现循环依赖的问题,而objection正好可以处理这些问题。

 

下面我们来看下使用objection如何实现上面的需求。

 

      首先,定义一个协议(protocol),然后通过objection来注册这个协议对应的Class,需要的时候,可以获取该协议对应的object。对于使用方无需关心到底使用的是哪个Class,反正该有的方法、属性都有了(在协议中指定)。这样就去除了对某个特定Class的依赖。也就是通常所说的「面向接口编程」。

 

Ios代码


1.    // 获取默认的injector,这个injector已经注册过BViewControllerProtocol了

2.    JSObjectionInjector *injector = [JSObjection defaultInjector];

3.     

4.    // 获取BViewControllerProtocol对应的Object

5.    UIViewController <BViewControllerProtocol> *vc = [injector getObject:@protocol(BViewControllerProtocol)];

6.     

7.    // 拿到vc后,设置它的属性,因为在BViewControllerProtocol里有定义对应的属性,所以不会有warning

8.    vc.backgroundColor = [UIColor redColor];

9.    vc.currentIndex = 1000;

10.  [self.navigationController pushViewController:vc animated:YES];



 

可以看到这里没有引用BViewController。

 

再来看看这个BViewControllerProtocol是如何注册到injector中的,这里涉及到了Module,对Protocol的注册都是在Module中完成的。Module只要继承JSObjectionModule这个Class即可。

 

Ios代码


1.    @interface BViewControllerModule : JSObjectionModule

2.     

3.    @end

4.     

5.    @implementation BViewControllerModule

6.     

7.    - (void)configure {

8.    [self bindClass:[BViewController class] toProtocol:@protocol(BViewControllerProtocol)];

9.    }

10.   

11.  @end


复制代码

 

绑定操作是在configure方法里进行的,这个方法在被添加到injector里时会被自动触发。

 

Ios代码


1.    // 获取默认的injector

2.    JSObjectionInjector *injector = [JSObjection defaultInjector];

3.     

4.    // 如果默认的injector不存在,就新建一个

5.    injector = injector ? : [JSObjection createInjector];

6.     

7.    // 往这个injector里注册Module

8.    injector = [injector withModule:[[BViewControllerModule alloc] init]];

9.     

10.  // 设置该injector为默认的injector

11.  [JSObjection setDefaultInjector:injector];


复制代码

 

上面这段代码可以直接放到 + (void)load里执行,这样就可以避免在AppDelegate里import各种Module了。

 

因为我们无法直接获得对应的Class,所以必须要在协议里定义好对外暴露的方法和属性,然后该Class也要实现该协议。

 

Ios代码

1.    - (void)viewDidLoad {

2.    [super viewDidLoad];

3.     

4.    UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];

5.    button.frame = CGRectMake(100, 100, 100, 30);

6.    [button setTitle:@"PUSH" forState:UIControlStateNormal];

7.    [button addTarget:self action:@selector(buttonTapped) forControlEvents:UIControlEventTouchUpInside];

8.    [self.view addSubview:button];

9.    }

10.   

11.  - (void)buttonTapped {

12.  ViewControllerB *vc = [[ViewControllerB alloc] init];

13.  [self.navigationController pushViewController:vc animated:YES];

14.  }



 

通过objection实现依赖注入后,就能更好地实现SRP(Single Responsibility Principle),代码更简洁。

 


标签:

热门专区

暂无热门资讯

课程推荐

微信
微博
15311698296

全国免费咨询热线

邮箱:codingke@1000phone.com

官方群:148715490

北京千锋互联科技有限公司版权所有   北京市海淀区宝盛北里西区28号中关村智诚科创大厦4层
京ICP备12003911号-6   Copyright © 2013 - 2019

京公网安备 11010802030908号