Syringe: iOS and OSX Dependency Injection framework
Dependency Injection is very well known tool in land of Boring Business Technologies like Java and .NET. Many benefits include promotion of modular architecture by loose coupling, easy escape from dreaded singleton pattern (in favor of simulated singleton pattern
. Dependency-injected code is also much easier to test.
How DI works? In simple words, it is sometimes called an implementation of "The Hollywood Principle". Hollywood Principle is named after response given to amateur wanna-be actors after audition: "don't call us, we call you". But contrary to Hollywood producers, DI frameworks will keep the promise. Imagine class Car and its close collaborator, Engine. In old times, you would create one class, and in Car's constructor for example, one will create a instance of Engine. And it works perfectly, but only in programming book examples. Often you will have many more collaborators, and soon you will need to provide the same instance of Engine to other classes.
And here devil starts smiling and whispering to your ear: "Dear developer, having trouble with this network of connections between classes? Try singleton pattern, you won't have to worry about passing once created instance to all interested parties". And until recently, most Objective-C developers listened to Singleton Devil.
And here comes the
Syringe Framework
Truly agile Dependency Injection for Objective-C. Ready to grab from GitHub. Featured on SoftPedia. Fast and lightweight. And very simple to use.
I designed Syringe inspired by best parts of Spring Framework and Google Guice, and tried to make it lightweight and simple. First of all, Syringe is
Annotation-driven
You're right: there are no annotations in Objective-C, but there are Protocols (called "interfaces" by Java/.NET guys). So any class you wish to be injected should be marked by implementing Injectable protocol. Like in this example:
@interface Car : NSObject <Injectable> { … }
Since then, all ivars of Car type in classes that are managed by Syringe will be assigned by reference to cached instance of Car. And if Car has ivars of other types that are marked with Injectable protocol, they will be populated too.
Most difficult part is start
Not in Syringe case: on very beginning there is object not managed by Syringe that has to start everything. Convenient C macro makes it clean and simple:
Car *car = inject(Car);
And that's all. No XML configuration, no container to configure and start. Syringe starts automatically upon first use of inject macro. If you want more control, you can start rolling everything manually:
[BeanFactory bootstrap];
Sometimes after Syringe-managed instance is created you may want to run some initailization code, and be sure that all collaborators are connected. This is possible by
Post-initialization
and simply adding InitializingBean protocol:
@interface Car : NSObject <Injectable,InitializingBean> -(void) afterPropertiesSet { … }
and implementing protocol's only method: afterPropertiesSet.
Inverse Spider-Man Principle
With great simplicity, there comes low flexibility. I am aware of that, but Syringe is a idea that I had on my mind for months. It was meant to solve my problem. But if it does not solve yours - let me know and feel free to fork me.

Polski
English




