PDA

View Full Version : View inside NIB file is not loading. Why?




tutiplain
Apr 18, 2011, 01:13 PM
Hi all,

I am setting up a View created in a NIB file, but I can't get it to display. I must be missing something. Here's my setup: I have a NIB file with just the view in it (and all the NIB's subviews or controls). File's owner for the NIB is set to a custom UIViewController subclass. In Interface Builder, the view is connected to File Owner's view connector (thereby binding it to "self.view" within the class). The app begins with another view and a UINavigationController, and an instance of the second view is pushed into the stack in the "didFinishLaunchingWithOptions" message, like so:


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.

//self.window.rootViewController = self.viewController;
self.window.rootViewController = navBar;

SecondViewController *second = [[SecondViewController alloc] init];
second.view = [[UIView alloc] init];
[navBar pushViewController:second animated:YES];
[self.window makeKeyAndVisible];
return YES;
}



When I run it, the second view is successfully displayed (my navigation controller animates, and the first view scrolls out of sight), but it is blank! What could I possibly be missing, especially considering that I have another project set up exactly the same way, and it works?

Thanks for any info.



dejo
Apr 18, 2011, 03:09 PM
What is the purpose of this line?:
second.view = [[UIView alloc] init];

tutiplain
Apr 18, 2011, 11:56 PM
Hi dejo,

Thanks for your reply. You were right, that line was the cause of the problem. I think I added it at one moment where I was getting a "view outlet is not set" message, and forgot to remove it later.

That being said... the project I originally posted about was simply a test project to ask the question. I still can't get it to work correctly, even though I do have another UIViewController setup in the same manner and it works.

Here is the code which navigates to the views:



-(IBAction)showCalculationView
{
SueldoCalcViewController *calcScreen = [[SueldoCalcViewController alloc] init];
//[navBar pushViewController:calcScreen animated:YES];
[self.navigationController pushViewController:calcScreen animated:YES];
}

-(IBAction)showDiscountInfoView
{
DiscountInfoViewController* discScreen = [[DiscountInfoViewController alloc] init];
[self.navigationController pushViewController:discScreen animated:YES];
}


The first function properly shows its view, the second one doesn't. Both SueldoCalcViewController and DiscountInfoViewController are subclasses of UIViewController, and both are set as File's Owner each in their own NIB file, which only have one view and some controls on them (and the View properties are correctly connected in IB).

Here's the code for DiscountInfoViewController class:



#import "DiscountInfoViewController.h"


@implementation DiscountInfoViewController
@synthesize txtName;
@synthesize txtPercent;
@synthesize txtActDate;


- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}

- (void)dealloc
{
[super dealloc];
[txtActDate release];
[txtName release];
[txtPercent release];
}


-(id) init
{
[super init];
//load additional resources

return self;
}

-(IBAction) saveDiscount
{
NSLog(@"saveDiscount called");
}

- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];

// Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView
{
}
*/


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
}

- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}

/*- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}*/

@end



As you can see, here I am not manually [[alloc] init] the view property. What else could I be missing?

wlh99
Apr 19, 2011, 12:14 AM
DiscountInfoViewController* discScreen = [[DiscountInfoViewController alloc] init];

Is init really what you want, or should you use initWithNibName?

tutiplain
Apr 19, 2011, 07:21 AM
Hi,

I see your point. I will try with initWithNibName and report back the results. However, if you look at my code I have two methods that push view controllers in a similar manner. The method named showCalculationView also inits the view controller with a [[alloc] init] statement, and this one works fine. In both cases, as I mentioned, the File's Owner of each NIB file is set to the appropiate class. This, I believe, is what causes the first view controller to function and automatically load its nib contents. The second one, however... doesn't.

Another detail that may or may not have relevance: I created this project in the previous version of Xcode and the sdk (don't remember the exact number), but am working now on XCode 4.0. So the code and NIB files for the method "showCalculationView" were made in XCode 3, while the code and NIB for "showDiscountInfoView" was made in XCode 4.

Any additional info will be greatly appreciated.

wlh99
Apr 19, 2011, 10:28 AM
Hi,

... In both cases, as I mentioned, the File's Owner of each NIB file is set to the appropiate class. This, I believe, is what causes the first view controller to function and automatically load its nib contents. The second one, however...



This is not how NIBs get loaded. The following code is copied from the default navigation view app that XCode creates. This is how I typically do it.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {


<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:@"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];

}

I think it is done differently in a tab bar based app, although it is been a while I don't recall exactly. I think there is a property on the tab bar item object in the rootview.nib that sets the filenames for subsequent views.

PhoneyDeveloper
Apr 19, 2011, 11:06 AM
Using alloc/init to create a view controller that has its view hierarchy loaded from a nib works fine. The requirement is that the nib must be named the same as the view controller class. This is the default when you create a new view controller with a nib using the New File menu item.

Is it possible that the second view controller's nib has had its name changed?

Is initWithNibName called in that view controller when you call alloc/init?

BTW, you need to call super dealloc LAST in any class's dealloc method.

tutiplain
Apr 19, 2011, 03:37 PM
Hi, and thanks to everyone for your replies. I tried with "initWithNibName:bundle:" and it worked! Thx for that, wlh99. And, as suggested by PhoneyDeveloper, yes, the second NIB file has a different name from its "associated" class. The reason is that I create the NIB first, and then I create the class. I will keep this in mind for future occasions.

Many thx for helping me clear that up!

PhoneyDeveloper
Apr 19, 2011, 04:29 PM
What I usually do in the case where the nib and the class have different names is override init in the view controller like this:

- (id)init
{
if ((self = [super initWithNibName:@"nameOfTheNib" bundle:nil])) {
// Custom initialization
}
return self;
}

and then create the view controller with alloc/init