Reliant is a Dependency Injection (DI) framework for Objective-C, both for OS X and iOS. Its goal is to make its use as simple as possible, while not limiting possibilities. It aims to have as little impact as possible on your project code. It also aims to be loyal to Objective-C's dynamic nature.
In this section we will get you started with Reliant as quick as possible, if you want to know more (or in other words, the TL;DR version) we suggest you take a look at our wiki pages
The easiest way to install Reliant is via CocoaPods
Add the following line to your Podfile:
pod 'Reliant'
Then run pod install
or pod update
for more information about CocoaPods, go to http://cocoapods.org
We suggest that you first take a look at our quick-start 'Hello World' tutorial and sample app, found under the Examples folder in the Reliant repository.
The following documentation is based on our more elaborate sample app, which can also be found under the Examples folder in the Reliant repository.
You first need a context in which Reliant will look for your specific objects. The default way to configure such a
context is through a configuration class. The example contains some of these. The application wide context is configured
with the AppConfiguration
class.
//Header file omitted
@implementation AppConfiguration
- (id<StringProvider>)createSingletonStringProvider {
return [[DefaultStringProvider alloc] init];
}
@end
In this very simple example we have the concept of a StringProvider
which will generate some strings shown by various
views in our application. We configure Reliant to create a "singleton" instance of this string provider. The reason why
you would use dependency injection is that you can avoid hard dependencies to implementations. That's why we have
a StringProvider
protocol. The configuration will create an actual implementation instance, but that instance is hidden
from the actual dependent application code. In this case we use the DefaultStringProvider
.
Bootstrapping a context is very simple. Since we have a configuration for a context which is meant to be used throughout the entire application, we will bootstrap this context in the application delegate.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self ocsBootstrapAndBindObjectContextWithConfiguratorFromClass:[AppConfiguration class]];
}
This single line of code is the easiest way to bootstrap a context. It wil start the context with the specified
configuration class, and then bind that context to self
which in this case means your application delegate.
Reliant injects all your objects specified in the configuration. Injection can be done in two ways:
- Initializer injection
- Property injection
For simplicity's sake we will use property injection in these examples.
We actually prefer initializer injection over property injection, but we will get into that in our wiki pages.
Let's say that our DefaultStringProvider
implementation needs a StringGenerator
to generate some strings.
We could do this by simply adding a property named stringGenerator
on our DefaultStringProvider
.
@interface DefaultStringProvider : NSObject<StringProvider>
@property (nonatomic, strong) id<StringGenerator> stringGenerator;
@end
Now we just need to add another configuration method to our AppConfiguration
class.
//Inside the implementation of our AppConfiguration
- (id<StringGenerator>)createSingletonStringGenerator {
return [[DefaultStringGenerator alloc] init];
}
With that, when you start your application, both the DefaultStringProvider
and DefaultStringGenerator
are being
created for the AppDelegate's context. Remember when we said they were created as "singletons"? Well, they are not real
singletons, but they are in the AppDelegate
context. When you ask the context for this object, it will always return
the same instance, guaranteed.
For those of you who prefer to put the property in an anonymous class extension, as we do, that would work as well.
After the creation of an object, it will be injected with other objects known by the context it is created for. So in this
case the DefaultStringGenerator
is injected in the DefaultStringProvider
through its stringGenerator
property.
You easily succeeded in loosly coupling the StringGenerator
to your DefaultStringProvider
class.
It might not always be possible to configure your objects through Reliant. For instance, a view controller might get created by a storyboard or by your applications code somewhere. In these cases Reliant will not be able to inject your object automatically. However, injecting an object is a one-liner again:
[self ocsInject];
This will locate a context based on self
, and then inject self
with objects known to the found context.
Reliant figures out which objects to inject by their given name. In this case, the names of our object are stringProvider
and stringGenerator
. That is why we named the property in DefaultStringProvider
as such. The names of the objects are
specified by your configurator. In this case Reliant derives the name from the method names. All text which comes after the
createSingleton
is seen as a name. The tentative reader might argue that the names should be StringGenerator and
StringProvider (with starting capital), in fact that is true. However, Reliant has created aliases for these objects
in their camelcase form.
Do not forget to check our wiki pages for more details on what is discussed above. Our API documentation is available via cocoadocs.org
If not via GitHub, find us on twitter: @AppFoundryBE or @mikeseghers
Reliant is released under MIT licence