views:

617

answers:

2

I think I'm missing something fundamental and so I want to ask the community for some help. I'm building an app based around a basic iPhone Utility Application. My MainView and FlipsideView share some elements so I have created separate ViewControllers and nib files for those pieces. In order to do this I have done the following: 1. Created a viewcontroller called searchDateViewController which is the file's owner of searchDateView.xib 2. searchDateView.xib is basically a UIView with a UILabel inside, the view is wired up correctly 3. Inside both MainViewController.m and FlipsideViewController.m I add a subview as folllows:

- (void)loadView{
    [super loadView];
    searchDateViewController = [[SearchDateViewController alloc] initWithNibName:@"SearchDateView" bundle:nil];
    [[searchDateViewController view] setFrame:[searchDateView frame]];
    [[self view] addSubview:[searchDateViewController view]];

...
}

Everything displays and works just fine. Basically depending on actions that happen in each of the main and flipside views the UILabel of the nib is changed. However, I wanted to do something slightly different if the searchDateViewController is loaded from the MainView or the FlipsideView. However, I can't seem to figure out which ViewController is adding the searchDateViewController subview.

In searchDateViewController I tried:

- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"superview %@", self.view.superview);
    NSLog(@"parentviewcontroller %@", self.parentViewController);
}

In both cases I get nil.

So my question is - can I find out which ViewController is adding searchDateViewController a a subview? If so how? Or if my logic here is completely messed up, how should I be doing this?

Thanks!

A: 

ViewController and views are completely separate.

In most cases, when you add a subview to a parent view you don't add its controller to the parent's viewController. The exception to this rule is the navigation controller which adds the controller instead of the view to maintain a hierarchy of view controllers.

Your SearchDate viewController can't find a parent controller because you never assigned one and the system does not do it automatically. You can just assign a parent controller when you evoke the view from another controller.

searchDateViewController.parentController=self;
TechZen
My understanding is that parentViewController is ready-only so I can't set it (in fact I get an error when I try).
deadroxy
Quick followup - I guess you might have meant as Ole did to create a new property inside the SearchDateViewController to hold this info. That works, but I still have lingering concerns about Ole's comment about this strategy (of using UIViewControllers as subviews) generally going against good design principles...
deadroxy
Your right it is read only. I just assumed it was read/write because the navigation controller sets the attribute. I wonder how the navigation controller sets the attribute? Ole is correct that having multiple controllers on the same visible screen is bad practice. The API doesn't support that easily.
TechZen
+1  A: 

viewDidLoad is invoked when the view controller has loaded its view. In your case, that happends in this line:

[[searchDateViewController view] setFrame:[searchDateView frame]];

At that moment, you haven't yet called addSubview: so it is no wonder the view's superview is nil.

To solve your problem, you should define a property inside SearchDateViewController to distinguish between the different cases. This property would then be set accordingly by the parent controller that creates the SearchDateViewController instance.

Generally, I do not think it is a good idea to use a UIViewController subclass as a controller for a view that is used as a subview of one or several fullscreen views rather than be used as a fullscreen view itself. Much of UIViewController's logic works on the assumption that it is used to manage a fullscreen view. For instance, with your design, I think it's possible that SearchDateViewController will modify the view's frame when the device orientation changes etc. Since you don't need all this functionality for a non-fullscreen subview, I suggest you subclass your SearchDateViewController directly from NSObject.

Ole Begemann
Okay thanks for pointing me in the right direction regarding subviews and UIViewController subclasses. If I make SearchDateViewController a subclass of NSObject how is that going to affect the way I am adding the subviews and initing with the nib? I haven't found any examples of subviews as nsobjects rather than viewcontrollers but I want to start adopting whatever standard practice is in this case. Let me know if you have any more tips - thanks!Also - you both suggested using the parentcontroller, which makes sense, but what role does superview play? Would that be more appropriate here?
deadroxy
Making SearchDateViewController a subclass of NSObject does not remove your problem, it just avoids future problems because UIViewControllers are not really meant to be used for views that do not take up the entire window IMHO.To solve your problem, your view customization code should not rely on self.parentViewController or view.superview at all. Instead, define a property in SearchDateViewController (could be a BOOL or an enum) that you then query to decide how to customize the view. The object that creates the SearchDateViewController should set the property.
Ole Begemann
I did just as you said creating a property in the SearchDateViewController class which worked fine. However, I'm still puzzled as to how to transition from that being subclassed from UIViewController to UIView/NSObject. Specifically who becomes the file's owner of SearchDateView? I tried every which way and everything I've done results in errors...
deadroxy