TestsTested | ✓ |
LangLanguage | Obj-CObjective C |
License | MIT |
ReleasedLast Release | Dec 2014 |
Maintained by Unclaimed.
Context and Dependency Injection for Objective-C
Simple, easy and very powerful way to use context and dependency injection and interception for objective c development. CDI is designed to solve some common software development patterns like Dependency Injection / Inversion of Control, Singleton and Interception (an minimalistic AOP approach).
The main features are:
Using CDI will reduce the boilerplate code in many classes, increase readability and allow better testing. The interception functionality will also provide the ability to separate the implementation code by aspects like security, logging and other facets.
CDI does not depend on another framework, which means you can use any unit testing, mocking or other framework (see Limitation chapter).
Here are some samples:
@interface InjectExample: NSObject
// Let's say you have one class which implements the MyServiceProtocol
...
@property(nonatomic, readwrite) MyServiceProtocol *myService;
...
@end
@implementation InjectExample
...
// Using @inject instead of @synthesize will lookup the
// implementation class at runtime and create the instance automatically
@inject(myService);
...
@end
Full Sample Code:
@interface InjectExample: NSObject
...
// Let's say you have multiple classes which implements the MyServiceProtocol
@property(nonatomic, readwrite) MyServiceProtocol *myService;
...
@end
@implementation InjectExample
...
// Using @inject with an implementation class which will be
// used to create the myService instance
@inject(myService, MyServiceImplementation);
...
@end
@interface InjectExample: NSObject
...
// Let's say you have a property with a class type
@property(nonatomic, readwrite) NSDate *now;
...
@end
@implementation InjectExample
...
// Using @inject will create a new instance automatically
// containing the current date and time
@inject(now);
...
@end
@interface SingletonExample: NSObject
...
@end
// This annotation will produce a singleton implementation
// for SingletonExample. Inject it into other classes to
// access the unique instance.
@singleton(SingletonExample);
@implementation SingletonExample
...
@end
Full Sample Code:
// Override the auto-wiring by binding new implementation classes to use mocking objects.
// Your test just needs to use the bindProtocol or bindClass method in the setup of your
// Unit testing framework.
[[CDI sharedInstance] bindProtocol:@protocol(ExampleProtocol) with:[MyMock class]];
// This is a very simple method execution logger.
@interface MethodLoggerInterceptor : CDIInterceptor
@end
@implementation MethodLoggerInterceptor
// The invoke method is called on each method call.
-(void)invoke:(CDIInvocationContext *)context {
NSLog(@"--> Entering [%@:%@]", context.target, context.method);
[context execute];
NSLog(@"<-- Leaving [%@:%@]", context.target, context.method);
}
@end
@interface MyDemo : NSObject {
...
-(void)doDemo;
...
}
@intercept(MyDemo,MethodLoggerInterceptor)
@implementation MyDemo
...
// This method will be surrounded automatically with entering and leaving log messages.
-(void)doDemo {
...
}
...
@end
Full Sample Code:
To run the example project; clone the repo, and run pod install
from the Project directory first.
The injected elements are accessible after the initialization methods (init...)
.
CDI is under development and there still may be some unknown issues.
Known issues are:
Open:
Fixed:
Please report issues here.
CDI has to be enabled before it can be used for development. Open the AppDelegate.m
(or any similar class which is executed at the beginning of the application) and add the following initialize
method to the implementation:
#import "AppDelegate.h"
#import <CDI.h>
@implementation AppDelegate
...
+(void)initialize {
[super initialize];
// Enable context and dependency injection
[CDI initialize];
}
@end
CDI is available under the MIT license. See the LICENSE file for more information.