52

Interface Builder can be used for basic dependency injection in a Cocoa app, but is anyone aware of more complete dependency injection frameworks for Objective-C/Cocoa for when you don't want to instantiate objects in a NIB file?

Edit

To clarify, I recognize that IB can be used for basic DI, but I'm looking for a framework with more complete functionality, including separate production and testing configurations, along the lines of Groovy or Springs.

Barry Wark
  • 107,306
  • 24
  • 181
  • 206
  • 2
    Checkout out www.typhoonframework.org – Jasper Blues Feb 20 '13 at 03:36
  • 1
    And here is another one https://github.com/railsware/BloodMagic – AlexDenisov Nov 17 '13 at 11:52
  • Java is most certainly still considered to be a late binding language. Although it uses vtable-style dispatch like C++, by virtue of having a virtual machine and class-loader system, run-time method interception is still possible. The approach is somewhat more cumbersome than messaging (objective-c) and requires heavier tooling to make it easy to use - things like JSDK dynamic proxies, cglib/asm or a JVM agent. This enables things like AOP or 'manged objects' (hibernate/core data), but has little to do with DI. I don't think the *'java static - needs DI, Objective-C dynamic'* applies. – Jasper Blues Apr 23 '15 at 02:13

12 Answers12

29

objection by AtomicObject. It is molded in the image of Guice.

Jasper Blues
  • 28,258
  • 22
  • 102
  • 185
justice
  • 400
  • 1
  • 5
  • 6
  • 2
    Wow, that looks pretty wicked. I still have no idea why I would need this, but I'm willing to learn. – steipete Mar 28 '11 at 14:24
  • 2
    Thanks, steipete. Dependency Injection is most useful in application development. The most obvious benefit is removing the necessity of having to manually construct objects throughout your code base or maintain factories (or factory methods). DI libraries also tend to favor separation of responsibilities through composition -- which I like. It is not, however, ideal for developing libraries or "APIs" since DI makes the dependencies of an object *obvious*. A good article on DI can be found [here](http://martinfowler.com/articles/injection.html). – justice Mar 28 '11 at 16:22
16

I'll go out on a limb and speak on this. Dependency injection as described by the top answer doesn't address the core issue that those seeking to use it are having. We'd like a means of development where component A does not directly instantiate or reference component B. Component A is bound by protocol to component B and is not referenced at all by component A. This allows component B to be replaced at anytime without ever touching component A. I down voted but I will research your references as it seems there are a few who agree with you. I'm not trying to debate, just looking to learn. I'd like to understand more about the "nope you don't need to do that" approach.

Cliff
  • 10,586
  • 7
  • 61
  • 102
  • Key-Value-Coding "allows component B to be replaced at anytime without ever touching component A". – MacMark Oct 12 '11 at 11:14
  • KVO doesn't explain how component A gets a reference to component B. In most typical uses of KVO (or as you describe) component B would instantiate A and bind to A's properties. Yes B could be any object with A caring but B still "knows" and instantiates A. Maybe I'm missing something? – Cliff Oct 13 '11 at 00:36
  • 2
    Thought about it some more and I think I understand a little. KVC and duck typing allows any property access and message sending to a given object regardless of implementation. That doesn't address the question of who instantiates the dependencies where A -> B. One could use IB to wire things together which is fun but not as feature filled as an actual dependency injector. – Cliff Oct 13 '11 at 00:41
  • 1
    Someone has to instantiate objects. In the Java with Spring case, it's the Spring container. For Interface Builder "stuff", it's IB and the runtime (ignoring NSProxy details). In the rest of the app, it's probably some part of your code. With Objective C categories and duck typing solve the issue of dynamic instansiation to change behavior, the only stuff you're left with is the code that wires up your own objects. Why go to the extreme of extracting that into some XML file when you don't need the rest of the DI benefits? – Otto Jun 18 '12 at 18:39
  • 1
    @Otto I somehow missed your response several months ago. I understand how you can do some types of DI using NIB files and have done so myself in absence of a Spring container. However, nib files do not scale as a true DI container. (Things may have improved this past year while I took time off of iOS.) Also, I cannot see where categories fill any benefits of DI that I am aware of. I've never used DI to change behavior during runtime (you may be confusing DI w/ AOP provided by the Springframework). These are 2 orthogonal concerns. – Cliff Oct 09 '12 at 15:25
  • I'm looking to do DI as to making unit-test easier (without which I would need a lot of test doubles). And I currently think that a manual DI cracks open the the abstraction I intend to seal. Is the job of a DI framework to abstract the object instantiation from whoever is using the consumer of the dependency? – huggie Dec 05 '13 at 09:49
11

I think you'll find that you don't need it in late-binding languages like Objective C, Ruby, Lisp and so on. Like Jamis' revelation that he was going down an overly complex path when he tried to build needle, a DI framework for Ruby- Net::SSH revisited.

Here are some links that will hopefully give you some sample code to do similar things in Objective C. With categories you can essentially change any class's behavior at runtime. See Mac Developer Tips – Objective-C: Categories and the Cocoa API docs on categories. Essentially you don't need some central place to ask for "the thing that does x" that is configurable, because you can just instantiate TheThingThatDoesX directly and if something else needs to change/hook into that behavior it can use categories.

Otto
  • 18,761
  • 15
  • 56
  • 62
  • 4
    I think it's telling that Brad Cox, the designer of Objective-C, has spent his life working on loose coupling and software reuse. The dynamic features of Objective-C are there to solve the problems DI solves for static languages. http://ieeexplore.ieee.org/iel2/190/267/00004852.pdf?arnumber=4852 – Paul Jan 29 '09 at 03:19
  • It's also telling that this Stack Overflow post is now the top Google result for "dependency injection objective-c" and "dependency injection cocoa". – Otto Jan 29 '09 at 19:41
  • 9
    Categories are great - but I personally don't see how they get you around DI. Modifying an existing class is not the same as changing a full implementation. – tcurdt Jan 30 '09 at 12:45
  • Better response, post caffeine - I was more trying to point toward the idioms to hopefully be more helpful than "nope you don't need to do that" without any kind of pointer to something that might help solve the need. – Otto Jan 30 '09 at 13:38
  • 5
    After re-reading Brad Cox's paper, I agree... he is a hero. But a system that _allows_ late binding is not the same as DI. I'm tempted to give you the bounty for reopening my eyes to the coolnes of ObjC, but it hasn't fully answered my question in the end. – Barry Wark Jan 30 '09 at 22:29
  • 2
    ...In particular, I'm looking for a framework that helps separate object graph construction from program logic. – Barry Wark Jan 30 '09 at 22:30
  • 2
    Does Core Data not do what you want? Remember, Obj-C uses duck typing, your view isn't going to care what kind of object it your controller gives it (assuming MVC, natch). I don't think I'm understanding the problem you want to solve. Maybe start a whole 'nother question with a specific example? – Otto Jan 31 '09 at 00:22
  • @Otto - your Cocoa API ref has gone stale. Similar is now at: http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocCategories.html – martin clayton Dec 06 '09 at 21:49
  • @martin fixed the link, thanks. – Otto Dec 21 '09 at 07:04
  • 59
    This answer does not reflect the core purpose behind dependency injection. The idea is not to override a class behavior at runtime, rather it is to eliminate hard bindings between desperate components. Could you explain how categories address that? – Cliff Jun 28 '11 at 18:07
  • https://github.com/atomicobject/objection mentioned by @wicket is a real DI library. – chrish Jul 12 '11 at 17:54
  • 4
    I don't see how this accepted answer answers the question of the OP. DI is about loose coupling and good application design. Classes/objects should only fulfill a specific purpose. I find myself writing lots of single purpose classes and injecting them into my object's constructors than before I was using DI (in Java). Shouldn't that also be applicable for Objective-C? – Sven Jacobs May 08 '12 at 10:37
  • @Sven Sure it's applicable to Objective C. It's just that there are language features that help you get there, you don't need a separate framework. – Otto May 26 '12 at 02:50
  • 3
    @Cliff If the components are truly "desperate," then maybe they won't mind being bound together? – jpswain Oct 08 '12 at 23:48
  • 2
    @orange80 I'm not sure I follow. Could you explain how a language feature that allows you to alter the behavior of an object at runtime addresses the need for objects to be used independent of on another? It's like saying, "this car has a Bose surround sound stereo system so there's really no need for an air-conditioner unit!" – Cliff Oct 09 '12 at 15:15
  • 2
    @Cliff sorry, it was just a dumb joke... you wrote "desperate" instead of "disparate" – jpswain Oct 09 '12 at 17:52
  • 1
    Oh, hahaha! Boy do I feel silly! Yes, my components have been longing to be bound in matrimony! – Cliff Oct 11 '12 at 22:09
  • Late binding is not the same as Inversion of Control, of which Dependency Injection is an example - even though DI does offer late binding as an advantage to static languages, it's not the only reason for DI – stifin Jun 15 '14 at 16:59
5

Typhoon

Almost one year ago, I released: https://github.com/typhoon-framework/Typhoon

The Typhoon-website lists the key features. A quick summary:

  • Non-invasive. No macros or XML required. Uses a powerful Objective-C runtime approach.

  • Makes it easy to have multiple configurations of the same base-class or protocol.

  • No magic strings - supports IDE refactoring, code-completion and compile-time checking.

  • Supports injection of view controllers and storyboard integration.

  • Supports both initializer and property injection, plus life-cycle management.

  • Powerful memory management features. Provides pre-configured objects, without the memory overhead of singletons.

  • Excellent support for circular dependencies.

  • Lean. It has a very low footprint, so is appropriate for CPU and memory constrained devices.

  • Battle-tested - used in all kinds of Appstore-featured apps

  • An internationally distributed core team (we even monitor StackOverflow), so support for any of your questions are never far away :)

API Docs and sample app

Quality Control:

We also maintain a robust quality control system.

  • Every commit triggers a series of regression tests
  • We maintain high test coverage.
Jasper Blues
  • 28,258
  • 22
  • 102
  • 185
4

You don't have to instantiate the object in the NIB file. If you set the File's Owner to your object's class and then link things in the view/window/whatever up to that, you can set your object as the owner at runtime by loading the nib file manually. That way you can have a dynamic instance of an object that still gets dependencies injected properly.

Jason Coco
  • 77,985
  • 20
  • 184
  • 180
  • But what about dependency injection for objects that are not the nib owner? I can instantiate them in the nib and thus use IB for dependency injection, but that's not a very scalable solution (the nib file quickly becomes unwieldy) – Barry Wark Nov 21 '08 at 21:45
  • You say "The Nib File", as if there was only one. You can have as many nib files as you like, which is not unwieldy at all. A nib doesn't even have to have an owner, you can put whatever objects you like in a NIB with no owner and pluck them out manually after you load the NIB file. – Kendall Helmstetter Gelner Nov 21 '08 at 21:56
  • I think I side-tracked the discussion a bit by mentioning IB. I'm looking for something along the lines of Spring or Groovy. – Barry Wark Jan 08 '09 at 00:04
3

What about dependecy injection implementation at Objective-IOC

NANNAV
  • 4,875
  • 4
  • 32
  • 50
mivasi
  • 31
  • 1
3

What about ObjectivePim? ObjectivePim

Víctor B.
  • 1,630
  • 2
  • 14
  • 21
1

I’ve written a very simple DI container, the code is on GitHub. It can only do the bare basics, ie. discover the dependencies of an object and satisfy them using other given objects. I have found that to be usable in real-world applications, the code is very simple and it’s fun to hack with.

zoul
  • 102,279
  • 44
  • 260
  • 354
-1

Has any looked at the Associative References feature of Mac OS X 10.6?

I believe with this it would be possible to build or already have something similar to DI. As far as I have seen however any reference that is needed in an object has to be fetched manually using objc_getAssociatedObject().

Manfred

Manfred
  • 169
  • 1
  • 2
  • Interesting idea. The associative references are intended to allow adding effective instance variables from, e.g., class categories without having to resort to ugly hacks. I'm not sure if it would lend itself to being the foundation of a DI system, but it's a very interesting idea. Thanks. – Barry Wark Feb 19 '10 at 16:38
  • You maybe might find this interesting, too. I just blogged about Dependency Injection on Objective-C. My first blog. http://swbymabe.wordpress.com/2010/02/20/objective-c-dependency-injection-sort-of/ – Manfred Feb 20 '10 at 01:07
  • I read your blog post, it looks nice and you obviously put a lot of work into it, but the question I was left with is: why do all that when you can just instantiate the object you need? I think @Otto puts it quite well in his answer. Thanks for the Associative References link, though, I'd not seen this before and I think it may well solve a problem I'm wrestling with. – Elise van Looij Apr 02 '10 at 10:51
  • Well. DI is for decoupling direct object dependencies. Using a dependency configuration objects can be wired together at runtime. It also helps a lot in unit testing where you can test objects with dependencies more easily. However the Objective-C runtime offers methods which are not available in languages where DI is much more needed. For example the Objective-C runtime function objc_setClass() (http://developer.apple.com/mac/library/documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html) can at runtime exchange the class of an object. This is not possible in Java. – Manfred May 07 '10 at 14:46
  • Very interesting feature you link to there: didn't know about that until now. I may be able to revise some pretty crufty code I have using this feature. Has anyone written a nice Objective-C wrapper for these pure C functions yet? – jkp Jun 06 '10 at 11:51
-1

Interface Builder does not do ANY dependency injection. It does not need to. Interface Builder serializes objects. When a nib is "awoken" (aka opened), there are no "dependencies" to resolve -- there are just properties to set. Very, very simple. Opening a nib relies solely on the NSCoding protocol and key-value coding.

Dependency injection, pretty much a make-work project at the best of times, or at best a generalized glue layer between components designed independently, is of no use in well written Objective-C code. You are asking for a tool that you don't need.

In Objective-C, software that requires an anonymous service declares a Protocol. Services then adopt this protocol. Clients load services as dynamic plug-ins. On the other hand, if the server was written prior to the client, it is simply a matter of writing a new plug-in which adapts the existing interface to the protocol. This is less work, and more straightforward than trying to define an intermediate data-driven system for "discovering" (please) an interface at runtime.

Is it not obvious to everyone that the big secret of DI is just that it's a way to write code in XML instead of in the native language? I'd really like to hear a good argument as to how XML is somehow a better programming language than a real programming language. It doesn't make any sense.

Bored
  • 33
  • 1
-2

DI is a property of a runtime execution enviroment requiring dynamic binding. I'm very new to Obj-C and Cocoa so I may speak out of turn. Unless I'm missing something, I don't see how one could implement DI except by interpreting Obj C rather than compiling it, or by modifying the runtime environment.

I suspect that the DI like behaviour of IB is because there is a domain specific runtime environment associated with apps that are built with it.

I'm happy to be corrected though.

Categories appear to be an implementation of mixin's, allowing dynamic dispatch of methods to a delegate. Rather cool and similar to Java's interface concept, thought the details differ and from the following, I can't see if constants can be defined in a category, though member fields cannot.

objective-c categories

NANNAV
  • 4,875
  • 4
  • 32
  • 50
  • Alas, whatever made you think that dynamic binding is foreign to Objective-C? [Have a look...](https://developer.apple.com/library/ios/documentation/General/Conceptual/DevPedia-CocoaCore/DynamicBinding.html) –  Jun 30 '15 at 04:57
-2

I work with Spring all day and I've checked Groovy. I'm by no means an XCode/Cocoa expert, but IB does only some dependency injection, which Groovy doesn't even really claims to be doing.

I reckon you are not looking for DI, but rather for a well compiled set of integrated libraries which saves you from typing a lot of code which other people also have typed. I think there are no Spring like frameworks for Cocoa because for some reason people tend to see "Open Source" as "not platform dependant" and therefore Cocoa is a bit left out in the cold.

Depending on your needs though, there are some nice free open source libraries available for Cocoa, all listed on CocoaDev in a nice list.

I know it isn't Spring, but I hope it helps.

Rolf
  • 7,098
  • 5
  • 38
  • 55