简介

  • 项目主页:https://github.com/atomicobject/objection
  • 实例下载: https://github.com/ios122/ios122

Objection 是一个轻量级的Objective-C依赖注入框架,可同时用于MacOS X
或者iOS.对于那些运用了Guice(一个Java依赖注入框架)的开发者,会深感Objection
似曾相识.Objection用来坐平等栽对立容易接受的措施来如果你尽量地不需要管住一个巨之XML容器或者手动创建对象.

特点

  • “Annotation” 基于依靠注入.
  • 无缝支持于定义集成与凭借扩展.
  • 自打定义绑定时类的创方式.
  • 元类绑定.
  • 说道绑定.
  • 实例对象绑定.
  • 变动名绑定.
  • 懒加载.
  • 赶忙计算的单例.
  • 由定义初始化方式.
  • 由定义参数与默认值.

系统要求

  • MacOS X 10.8 +
  • iOS 7.0 +

使用CocoaPods安装

留神podfile中得指明Objection的版号,否则无法安装成功.

pod 'Objection', '1.6.1' # 依赖注入.

下一场在需要之地方导入即可头文件即可:

#import <Objection/Objection.h>

使用 Objection

基础因此法

一个像样可采用宏 objection_register(可选)或
objection_register_singleton 注册到 objection. objection_requires
宏用来声明objection应该为此类的持有实例提供的依赖.objection_requires在近似的继续体系中也得以高枕无忧使用.

  • objection_requires
    宏,仅在打从针中取类的实例时,才发意义.从针中获类实例的章程,下面会实际讨论.
  • objection_requires
    宏声明指后,使用注射器来博此类实例时,会自动创建依赖类的实例,并赋值给响应的属性.
  • 假如用 objection_register_singleton
    宏注册一个像样,并坚称下注射器来获取此类的实例,那此类就毫无自己实现单例机制了.

示例.

@class Engine, Brakes;

@interface Car : NSObject

// 将会通过依赖注入赋值.
@property(nonatomic, strong) Engine *engine;
// 将会通过依赖注入赋值.
@property(nonatomic, strong) Brakes *brakes;
@property(nonatomic) BOOL awake;

@implementation Car
objection_requires(@"engine", @"brakes")
@synthesize engine, brakes, awake;
@end

下选择器定义依赖.

汝吗可以使用选择器来定义依赖.如果给定的选择器在现阶段作用域看无显现还是无法找到,编译器会发出一个警告.

示例

@implementation Car
objection_requires_sel(@selector(engine), @selector(brakes))
@synthesize engine, brakes, awake;
@end

自从Objection中获得对象.

可以创造一个针,然后从这注射器中取指定类或协议的一个实例.注射器各自管理好的目标上下文.这代表:Objection中之单例指的是一个针中只有存在一个某类的实例,并不一定是真的含义及之单例(即那种应用程序全局唯一的接近的实例对象).

- (void)someMethod {
  JSObjectionInjector *injector = [JSObjection createInjector];
  id car = [injector getObject:[Car class]];
}

一个叫Objection设置一个默认的注射器.这个设置器可以当你的施用或库内,全局可用.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
  JSObjectionInjector *injector = [JSObjection createInjector];
  [JSObjection setDefaultInjector:injector];
}

- (void)viewDidLoad {
  id myModel = [[JSObjection defaultInjector] getObject:[MyModel class]];
}

依赖注入

来或类似的实例对象并无是通过注射器创建的,此时只要未做特处理,依赖不见面吃正确处理,相关属性可能为nil.但是要是对以
objection_requires巨大指定依赖之情事,你可以通过injectDependencies:术来兑现:即使不动注射器也能确保依赖让满足.

@implementation JSTableModel
objection_requires(@"RESTClient")
- (void)awakeFromNib {
  [[JSObjection defaultInjector] injectDependencies:self];
}
@end

下标操作

Objection 已经支撑采取下标操作来打针上下缓来取得对象.

- (void)someMethod {
  JSObjectionInjector *injector = [JSObjection createInjector];
  id car = injector[[Car class]];
}

从Objection中创造的对象.

使一个靶急需掌握它们一旦相当被objection完全初始化的,可以实现方式awakeFromObjection
.注意:对象被Objection完全初始化时会见调用awakeFromObjection方法,你在此处可以在由定义之一部分操作;而awake只是一个例子中之自定义标记属性而已,并无是Objection的同样总理分.

示例

@implementation Car
//...
objection_register_singleton(Car)
  - (void)awakeFromObjection {
    self.awake = YES;
  }
@end  

靶工厂

一个目标足以由此对象工厂来打针上下和来博取对象.

自从定义JSObjectFactory属性,需要动用 objection_requires 宏来指明依赖,如
objection_requires(@”objectFactory”)
.这样当于针中取这近乎的实例时,会自行取与这注射器相关的JSObjectFactory对象工厂实例.

示例

@interface RequestDispatcher
@property(nonatomic, strong) JSObjectFactory *objectFactory
@end

@implementation RequestDispatcher
objection_requires(@"objectFactory") 

- (void)dispatch:(NSDictionary *)params
{
  Request *request = [self.objectFactory getObject:[Request class]];
  request.params = params;
  [request send];
}
@end

模块

一个模块就是相同组绑定信息.这些绑定信息之所以来给注射器增加额外的布置信息.它当做外部依赖以及绑定协议及类似或实例时特意有用.

实例和协和的绑定

  • 绑定一个商谈要近乎至拖欠种指定的有实例.
  • 绑定一个既注册到Objection的类到一个协议.

示例

@interface MyAppModule : JSObjectionModule {

}
@end

@implementation MyAppModule
- (void)configure {
  [self bind:[UIApplication sharedApplication] toClass:[UIApplication class]];
  [self bind:[UIApplication sharedApplication].delegate toProtocol:@protocol(UIApplicationDelegate)];
  [self bindClass:[MyAPIService class] toProtocol:@protocol(APIService)];
}

@end
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
  JSObjectionInjector *injector = [JSObjection createInjector:[[MyAppModule alloc] init]];
  [JSObjection setDefaultInjector:injector];
}

元类的绑定

有时候,我们只是是怀念采取依赖之有类的类方法.Objection可以透过协议显示地支持元类的绑定.这样就是不要再行创一个包装类来传递类方法.要留意的是,它需定义一个商谈来受Objection知道哪些绑定元类到注射器的对象上下文.

示例

@protocol ExternalUtility
  - (void)doSomething;  //!< 注意此处,确实是`-`减号.通常是不支持让元类直接支持协议的.此处是以类本身作为对象,来取执行协议,而不是使用该类的某一个实例.
@end

@interface ExternalUtility
  + (void)doSomething;
@end

@implementation ExternalUtility
  + (void)doSomething {...}
@end

// Module Configuration
- (void)configure {
  [self bindMetaClass:[ExternalUtility class] toProtocol:@protocol(ExternalUtility)];    
}

@interface SomeClass
{
  ...
}
//  使用 'assign' 是因为一个元类不受通常的 retain/release声明周期限制.
// 它将会一直存在,直到应用程序终止(类初始化 -> 应用终止),不管运行时有多少指向它的对象引用.
// 
@property (nonatomic, assign) id<ExternalUtility> externalUtility
@end

提供者

偶然你也许想要于Objection内部手动构造一个对象.提供者允许而利用于定义之机制来创造有项目的对象.你可创造一个
遵守 ObjectionProvider 商讨的目标,或者你得下一个 block
来创建对象.

而以了针对诸如供者,则原类中之
-awakeFromObjection措施在此类的实例通过注射器创建好后,不见面另行吃调用.

示例

@interface CarProvider : NSObject <JSObjectionProvider>
@end

@implementation CarProvider
- (id)provide:(JSObjectionInjector *)context arguments:(NSArray *)arguments {
  // 手动创建对象的代码
  return car;
}
@end

@implementation MyAppModule
- (void)configure {
    [self bindProvider:[[CarProvider alloc] init] toClass:[Car class]];
    [self bindBlock:^(JSObjectionInjector *context) {
      // 手动创建对象.
      return car;          
    } toClass:[Car class]];
}
@end

作用域

一个看似让用作模块作用域内之单例.相反,一个业已注册之单例在吗足以叫降级为针上下文中一个常见声明周期的实例对象.

也就是说,你发些许种植方法来指定类实例在注射器上下文是单例对象要一般对象.一栽是当相近实现中以
objection_register_singleton
宏,一种是在模块配置方式中指定作用域为JSObjectionScopeSingleton.

示例

@implementation MyAppModule
- (void)configure {
    [self bindClass:[Singleton class] inScope:JSObjectionScopeNormal];
    [self bindClass:[Car class] inScope:JSObjectionScopeSingleton];
}
@end

号绑定

暨一个接近还是协议的仗可以用 objection_requires_names
宏标记,这个宏使用属性别叫做字典作为参数.

示例

@interface ShinyCar : NSObject
@property (nonatomic, strong) Headlight *leftHeadlight;
@property (nonatomic, strong) Headlight *rightHeadlight;
@end

@implementation ShinyCar
objection_register(ShinyCar)
objection_requires_names((@{@"LeftHeadlight":@"leftHeadlight", @"RightHeadlight":@"rightHeadlight"}))
@synthesize leftHeadlight, rightHeadlight;
@end

@implementation NamedModule

- (void)configure
{
    [self bind:[[Headlight alloc]init] toClass:[Headlight class] named:@"RightHeadlight"];
    [self bindClass:[HIDHeadlight class] toClass:[Headlight class] named:@"LeftHeadlight"];

}
@end

尽早初始化的单例

而可将都登记的单例用作及早初始化的单例.及早初始化的单例,在注射器创建时创造,而不再是懒加载.

专注:如果以一个勿注册为单例的好像设置也及早初始化的单例,会挑起崩溃.

Example

@implementation MyAppModule
- (void)configure {
  [self registerEagerSingleton:[Car class]];
}

@end

从一个早就是的针派生一个初的注射器

一个新的针可以使 withModule:
方法从一个既是的针创建.这个新的注射器将见面和派生它的针拥有同样的绑定信息.

跟的相反,如果采取
withoutModuleOfType:,新注射器就不见面含有被标记为未含有的模块.

示例

injector = [otherInjector withModule:[[Level18Module alloc] init]] 
                          withoutModuleOfType:[Level17Module class]];

初始化

默认地,Objection 使用默认的初始化方法 init
创建对象.如果你想行使其它的初始化方法来初始化对象,可以凭
objection_initializer
宏.这个宏支持传递默认参数(暂时未支持标量参数,即着力类型参数,如数字).

默认参数示例

@implementation ViewController
objection_initializer(initWithNibName:bundle:, @"ViewController")
@end

由定义参数示例

@implementation ConfigurableCar
objection_requires(@"engine", @"brakes")
objection_initializer(initWithMake:model:)

@synthesize make;
@synthesize model;

- (instancetype)initWithMake:(NSString *)make model:(NSString *)model {
  ...
}
@end

- (void)buildCar {
  ConfigurableCar *car = [self.objectFactory getObjectWithArgs:[ConfigurableCar class], @"VW", @"Passat", nil];
  NSLog(@"Make: %@ Model: %@", car.make, car.model);
}

仿佛措施初始化

@implementation Truck
objection_requires(@"engine", @"brakes")
objection_initializer(truckWithMake:model:)
+ (instancetype)truckWithMake:(NSString *) make model: (NSString *)model {
  ...
}
@end

专用初始化方法

@implementation ConfigurableCar
- (instancetype) initWithModel:(NSString *)model {
    //....
}
@end

- (void)buildCar {
  ConfigurableCar *car = [self.objectFactory getObject:[ConfigurableCar class], 
                                           initializer: @selector(initWithModel:) 
                                           withArgumentList:@[@"Passat"]];
}

测试

设您正在以 Kiwi
来进行应用之测试,
请检出MSSpec.它提供了平等种将虚拟数据注入到公的测试标准中之利方式.

相关文章

网站地图xml地图