描述
Objection 是一个轻量级的Objective-C依赖注入框架,可同时用于MacOS X 或者iOS系统.对于那些使用过Guice(一个Java依赖注入框架)的开发者,会感觉Objection 似曾相识.Objection以一种相对容易接受的方式来使你尽可能地不需要管理一个庞大的XML容器或者手动创建对象.
特征
“Annotation”基于依赖注入
无缝支持自定义集成和依赖拓展
自定义类的创建
元类绑定
协议绑定
实例对象绑定
别名绑定
懒加载
及早初始化得单例
自定义初始化
** 默认和自定义参数
准备工作
CocoaPods
- 在Podfile文件中添加
1 | pod 'Objection', '1.6.1' |
- 安装Objection
1 | pod install |
- 包含头文件
1 |
##使用Objection
基本使用
一个类必须使用Objection的objection_register(可选)或者objection_register_singleton宏定义来注册。objection_register就是声明所依赖Objection创建的全部实例。
- 使用objection_register宏,参数是类名
1 | objection_register(@"类名") |
- 使用objection_requires宏,参数对象名(别名)
1 | objection_requires(@"对象名") |
例子
1 | @class Engine, Brakes; |
定义方法依赖
你也可以使用方法来定义依赖,如果你定义的方法不可见或者没有,那么编译器就会出现一个警告。
例子
1 | @implementation Car |
从Objection获取对象
可以创建一个注射器,然后从这个注射器中获取指定类或协议的一个实例.注射器各自管理自己的对象上下文.这意味着:Objection中的单例指的是一个注射器中只存在一个某个类的实例,并不一定是真正意义上的单例(即那种应用程序全局唯一的类的实例对象).
1 | - (void)someMethod { |
依赖注入
有可能类的实例对象并不是通过注射器创建的,此时如果不做特殊处理,依赖不会被正确处理,相关属性可能为nil.但是如果对于使用 objection_requires宏指定依赖的情况,你可以通过injectDependencies:方法来实现:即使不使用注射器也能保证依赖被满足
1 | @implementation JSTableModel |
下标操作
Objection已经支持使用下标操作,从注射器上下文来获取对象.
1 | - (void)someMethod { |
从Objection中创建的对象
如果一个对象需要知道它使合适被objection完全初始化的,可以实现方法awakeFromObjection .注意:对象被Objection完全初始化时会调用awakeFromObjection方法,你在这里可以加入自定义的一些操作;而awake只是一个例子中的自定义标记属性而已,并不是Objection的一部分.
1 | @implementation Car |
对象工厂
一个类可以通过对象工厂来从注射器上下文来获取对象.
自定义JSObjectFactory属性,需要使用 objection_requires 宏来指明依赖,如 objection_requires(@”objectFactory”) .这样当从注射器中获取这个类的实例时,会自动获取与此注射器相关的JSObjectFactory对象工厂实例.
1 | @interface RequestDispatcher |
模块
一个模块是一组绑定信息,它为注射器提供了额外的配置信息。它在整合外部依赖和绑定协议到类或实例时特别有用.
实例和协议的绑定
绑定一个协议或类到该类型指定的某个实例.
绑定一个已经注册到Objection的类到一个协议.
1 | @interface MyAppModule : JSObjectionModule { |
元类绑定
有时候,我们仅仅是想使用依赖的某个类的类方法.Objection可以通过协议显示地支持元类的绑定.这样就不用再创建一个包装类来传递类方法.要注意的是,它需要定义一个协议来让Objection知道如何绑定元类到注射器的对象上下文.
1 | @protocol ExternalUtility |
提供者
偶尔你可能想要在Objection内部手动构造一个对象.提供者允许你使用自定义的机制来创建某个类型的对象.你可以创建一个 遵守 ObjectionProvider 协议的对象,或者你可以使用一个 block 来创建对象.
如果使用了对像提供者,则原类中的 -awakeFromObjection方法在此类的实例通过注射器创建完成后,不会再被调用
1 | // CarProvider是一个提供类,遵守JSObjectionProvider协议 |
作用域
一个类被用作模块作用域内的单例.相反,一个已经注册的单例在也可以被降级为注射器上下文中一个普通声明周期的实例对象.
也就是说,你有两种方式来指定类实例在注射器上下文是单例对象还是普通对象.一种是在类实现中使用 objection_register_singleton 宏,一种是在模块配置方法中指定作用域为JSObjectionScopeSingleton.
1 | @implementation MyAppModule |
别名绑定
同一个类或者协议的依赖关系可以使用objection_requires_names宏标记,这个宏使用属性别名字典作为参数。
1 | @interface ShinyCar : NSObject |
及早初始化的单例
你可以将已经注册的单例用作及早初始化的单例.及早初始化的单例,在注射器创建时创建,而不再是懒加载.
注意:如果将一个未注册为单例的类设置为及早初始化的单例,会引起崩溃.
1 | @implementation MyAppModule |
从一个已经存在的注射器派生一个新的注射器
一个新的注射器可以使用 withModule: 方法从一个已经存在的注射器创建.这个新的注射器将会和派生它的注射器拥有同样的绑定信息.
与之相反,如果使用 withoutModuleOfType:,新注射器就不会包含已存在的注射器的绑定信息
1 | // 从otherInjector获取新的注射器injector,其中包含Level18Module模块的绑定信息,但是不包含Level17Module的绑定信息 |
初始化Initializers
默认情况下,Objection 使用默认的初始化方法 init 创建对象.如果你想使用其他的初始化方法来初始化对象,可以借助 objection_initializer 宏.这个宏支持传递默认参数(暂时不支持标量参数,即基本类型参数,如数字).
- 默认参数初始化
1 | @implementation ViewController |
- 自定义参数初始化
1 | @implementation ConfigurableCar |
类方法初始化
1 | @implementation Truck |
专用初始化
1 | @implementation ConfigurableCar |