Toran Billups
Toran Billups

Reputation: 27399

Can you accomplish some form of dependency injection in objective-c?

Currently I'm hard coding another object directly when needed and I'd like the ability to take this in through the init method (I assume?). In the code below I create a new HatService in the viewDidLoad method and I'd prefer not to do this this for testability / coupling reasons.

- (void)viewDidLoad
{
    [super viewDidLoad];
    HatService* hatService = [[HatService alloc] init];
    [hatService getHatById:self];
}

First question - How should this be done in objective-c? Second question - Should I be worried about this or doing it at all?

Update

Here is what I'm starting with but I never seem to hit the first init method during runtime. I have both declared in the interface - anything else I missed that would allow me to override this init method and inject the service dependency?

Note - I can hit this manually when I create the object myself but when the appDeleage does the work I don't see it hit this (how does the app delegate create this object without calling my init method?)

-(id)initWithHatService:(HatService *)service
{
  if (self = [super init])
  {
    [self setService:service];
  }
  return self;
}

-(id)init
{
  HatService* hatService = [[HatService alloc] init];
  return [self initWithHatService:hatService];
}

Upvotes: 3

Views: 1582

Answers (3)

Jasper Blues
Jasper Blues

Reputation: 28756

It's quite easy to implement the dependency injection design pattern in Objective-C. You could do it manually by creating an 'application assembly' class that defines individual collaborators.

Alternatively, you could use a framework to assist. I recently created a DI container called Typhoon: http://www.typhoonframework.org

Upvotes: 0

kubi
kubi

Reputation: 49364

The designated initializer for UIViewController is - (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle. You'll need to override this method if you want your view controller to be properly instantiated from a nib file, if that's what you're trying to do. Without seeing more code, it's impossible to tell, but this method is definitely being called somewhere.

Second, you need to re-write your -init method to look like this:

- (id)init {
    return [self initWithHatService:nil];
}

Every init method should call your designated initializer.

Finally, when you're dealing with view controllers, folks usually don't pass in properties in the init method. Instantiate the new controller, then pass it whatever service properties you like.

MyViewController *newContrlr = [[MyViewController alloc] initWithNibName:nil bundle:nil];
newContrlr.hatService = [[[HatService alloc] init] autorelease];

Upvotes: 6

Catfish_Man
Catfish_Man

Reputation: 41801

If you're asking how to pass an object to another object's init method, just declare your init method as taking one or more arguments. i.e. - (id) initWithHatService:(HatService *)serv; init methods aren't special in any way except convention in objective-c.

Unrelated: your -getHatById: method is curious. What are the memory management semantics of that? get-prefixed methods are pretty uncommon in Cocoa programs.

Upvotes: 1

Related Questions