2

I've been reading this thread on StackOverflow about dependency injection and am really keen to use the ideas given by the top rated answer. However, I'm having trouble extending them to work in my case and have looked everywhere for a solution but have had no luck.

To illustrate my situation in the simplest terms, lets say I have:

ViewController A - In which the user picks a photo
ViewController B - In which the user then picks a colour
ViewController C - In which the image and colour are displayed back to the user

I can see how I can use dependancy injection to specify that ViewController A should push ViewController B to the navigation controller once a photo has been selected, but where should I store the photo that was selected? How should I make it available to ViewController C to display?

Also, how should I tell ViewController B that it needs to push ViewController C when a colour has been picked?

The only solution I can think of which strictly follows the ideas of the above thread is to have a 'photo' property on ViewController B which gets set by ViewController A when it pushes it to the navigation controller. But this seems like a 'bad idea' to me because in general ViewController B should have no interest in photographs whatsoever as its sole purpose in life is to pick a colour and move on.

In trying to solve this I have come up with 2 possibilities:

1/ Make all ViewControllers report back to a central delegate.

This seems to fly in the face of what the dependency injection thread says, but it still seems the easiest way. I.e. ViewController A picks a photograph and tells a delegate about it. The delegate stores the photo for later and pushes ViewController B to the navigation controller. When a colour is picked, it stores this and pushes ViewController C, passing it the values for colour and photo it stored previously.

2/ Pass some kind of properties object between the controllers.

I could make an object with 'colour' and 'photo' properties and pass it to ViewController A. The photo property would be set in ViewController A and then the object would be passed to ViewController B, which would set the colour property before passing it on to ViewController C for display.

Both options seem kind of 'ok' to me, but neither feel quite right.

Maybe I've totally misunderstood dependency injection, in which case please let me know! Otherwise, any thoughts on the above would be tremendous.

Thank you in advance!

Community
  • 1
  • 1
Mason
  • 3,577
  • 2
  • 20
  • 11

3 Answers3

1

Here's how I would do it.

You first start off with a UINavigationController object which holds view controllers A, B and C. "A" gets pushed on first, "B" and then "C". As each view controller is pushed onto the "stack" of view controllers, they are all in memory. So when "C" is pushed on, "C" should ask the UINavigationController for the properties of "A" and "B" (photo and colour). Basically, UINavigationController is your bridge between C and the other two controllers (A and B).

David
  • 14,205
  • 20
  • 97
  • 144
  • Thanks for the quick reply David. It could definitely work like this, but each controller would have to be programmed to work only in that instance. For example, if I make C find A by looking at the nav controller's objectAtIndex:0, then I can't (for instance) decide down the line that I want to display something before A without needing to go and edit C to look at objectAtIndex:1 instead. I just sense there must a clever design pattern I can follow which will keep everything nice and general. – Mason Jan 21 '11 at 04:59
  • C doesn't have to know the index of A or B. You ask the navigation controller for the picture and colour. For instance, the navigation controller will have method of -getPicture, and -getColour. You send these messages to the navigation controller and it will return you a picture and a colour. The navigation controller will know how to get the picture and colour from A and B respectively. – David Jan 21 '11 at 05:02
  • I see, so subclass the navigation controller? I read this was a bad idea? – Mason Jan 21 '11 at 05:05
  • I don't know how else you would do it. You either need a central repository like a navigation controller or a dependency model where "A" passes the ball to "B" and then "C" through their initialization methods. – David Jan 21 '11 at 05:11
  • Yeah, these are the only 2 methods I can think of. Maybe these are the only ways, but I just feel like there must be a neater method or a reason to pick one over the other. – Mason Jan 21 '11 at 05:17
1

I don't think you need the full chain A->B->C.

A could call B, passing along a "selection" dictionary in the init method, and could then call C when it regains control after B returns. B and C would just know to "pick a (picture|color) & save results in the selection dictionary."

Then in viewDidAppear:, A has a simple state machine:

  • if no picture selected, push B (image picker)
  • else if no color selected, push C (color picker)
  • else display the image
David Gelhar
  • 27,873
  • 3
  • 67
  • 84
  • Hi David, thanks for the reply. I could definitely do it this way, but it wouldn't be good from a UI perspective to have the user return to view A before picking photo|colour in my real world case. – Mason Jan 21 '11 at 05:50
0

In case anyone is wondering the same thing, in the end I did option 1/ from my original question. Works nicely, feels maintainable and allows me to make very generic and reusable ViewControllers.

Mason
  • 3,577
  • 2
  • 20
  • 11