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开发者_Python百科 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];
}
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];
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.
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
精彩评论