views:

362

answers:

3

Edited for brevity:

How does a subview access properties in its superview and its superview's view controller? Easy enough to go down the chain. How do we go back up?

Original (verbose) post:

The immediate problem I'm trying to solve is simplifying the "birth" of a somewhat complex view. The large picture has to do with Nibs and how subclasses (of UIView in particular) that have beyond trivial initializers are reconstituted when the view loads.

I have some custom UIViews - subviews of a subview of my viewcontroller's view. When I instantiate these views in particular they need a reference to some properties (NSNumberFormatter, & NSDictionary) of the View Controller.

Currenty I use a method to instantiate them:

- (id)initWithFrame:(CGRect)frame items:(NSDictionary *)dictionary forEditingMode:(EditingMode)mode

I'm experimenting with moving them into a Nib to let them reconstitute themselves and running into basic design issues. One being I think I'm limited to initWithFrame as the default initializer?!? If so how can these objects look into the parent view controller and get a reference to the dictionary and some other properties?

Are there methods I could call within initWithFrame (similar to the ones that retrieve the UIApplication delegate) but would instead allow the child view to send methods to it's parent views and/or controllers?

Send in the MVC police, I'm sure I'm breaking something...

A: 

You can set up outlets that get connected to the view's superview or view controller and pull out the info in awakeFromNib. You need to use awakeFromNib instead of init* because the connections won't be created until then.

FYI, if you instantiate via a Nib, your designated initializer is initWithCoder:, not initWithFrame: (but don't use either for this).

Daniel Dickison
so you're saying put an IBOutlet in these subviews that points back to the superview or viewcontroller? i haven't come across that before...is it fairly common?
Meltemi
It's essentially the delegate pattern. You give the subview an outlet named `delegate`, and a delegate protocol (historically, this would be informal, although now you can use a formal protocol with optional methods). Then you make the superview conform to the protocol. Finally, you set it as the delegate, either in IB or with an accessor message.
Peter Hosey
Yup, like Peter said, your view controller essentially becomes a delegate for the subview. Make sure you make this an `assign` property or you'll end up with a retain cycle.
Daniel Dickison
+1  A: 

It should work the other way round.

The views only contain controls (text fields, etc.). The data lives in a model, and the view/window controllers mediate, accessing and setting the view controls values, synchronizing with the model.

OK, sometimes you may need to have a dictionary shared between the controller and the view. Then create a dictionary property in the view and set it in the awakeFromNib method of the nib owner.

IlDan
A: 

You should probably be doing this through the view controller manually just after the nib is loaded. This means that you will have to set the shared dictionary AFTER the view has been initialized. You might do it like so:

@interface MyViewController : UIViewController {
    IBOutlet MyView* view1;
    IBOutlet MyView* view2;
    IBOutlet MyView* view3;
}
@end

@implementation MyViewController

-(void) viewDidLoad;
{
    NSDictionary* sharedDict = //make the shared dictionary here;
    view1.sharedDict = sharedDict;
    view2.sharedDict = sharedDict;
    view3.sharedDict = sharedDict;
}

@end
Tom Dalling