In my navigation based application, initWithNibName method does not called/fire
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
I'm defining rootViewController (calViewController) in appdelegate like this
calViewController *objCalViewController = (calViewController *) [navController topViewController];
objCalViewController.context = [self managedObjectContext];
[window addSubview:navController.view];
[window makeKeyAndVisible];
Is this is the issue? Please give me a help
When your UIViewController is defined in a nib file or Storyboard (usually as an IBOutlet), initWithNibName:bundle: is not called, rather initWithCoder: is. This is the case when you use Interface Builder to set your UIViewController as part of UITabBarController or UINavigationController, and almost always when using Storyboards.
in your appdelegate.m do like this
calViewController *objCalViewController = [[calViewController alloc] initWithNibName:#"WebViewController_iPhone" bundle:nil];
objCalViewController.managedObjectContext = self.managedObjectContext;
navController = [[UINavigationController alloc] initWithRootViewController:objCalViewController];
[self.window setRootViewController:navController];
[window makeKeyAndVisible];
Ok lets say i have a viewController named TCViewController with
TCViewController.h, TCViewController.m and TCViewController.xib
and in TCViewController.m
i am overriding the below method.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
In my RootViewController i want to initialize TCViewController like this
RootViewController.m
-(void)viewDidLoad //not necessarily this one, can be any method
{
// This initialization calls the initWithNibname method implemented in TCViewController.m
TCViewController *viewController = [[TCViewController alloc] initWithNibName:#"TCViewController" bundle:nil];
[self.navigationController pushViewController:viewController animated:YES];
}
If you initialize a viewController like this, control will pass to the initWithNibName method in your subclass if you have implemented it.
Related
I'm diving into iOS development and I'm trying to create an iPad app that uses the split view layout, without using the UISplitViewController. I found this question already posted, but it's too vague to help me with my current level of iOS experience.
In short, I have a UIViewController class named MySplitViewController that contains two children view controllers, one for the master view and one for the detail view. I'm trying to implement this in a way that when I push an instance of MySplitViewController onto the nav stack, I get a table view (master) on the left and a detail view on the left. However, when I run my code, the entire split view is filled with the table view. How can I manually create a Split View layout? Here are my three view controller classes, they're very simple...
MySplitViewController.m
#import "MySplitViewController.h"
#import "MasterViewController.h"
#import "DetailViewController.h"
#interface MYSplitViewController (){}
#property (nonatomic, strong) MasterViewController *masterViewController;
#property (nonatomic, strong) DetailViewController *detailViewController;
#end
#implementation MySplitViewController
- (id)initWithCoder:(NSCoder *)aDecoder{
self = [super initWithCoder:aDecoder];
if (self) {
self.masterViewController = [[MasterViewController alloc] initWithNibName:nil bundle:nil];
self.detailViewController = [[DetailViewController alloc] initWithNibName:nil bundle:nil];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.frame = CGRectMake(0, 0, 768, 1004);
[self.view addSubview:self.masterViewController.view];
[self.masterViewController viewDidLoad];
[self.view addSubview:self.detailViewController.view];
[self.detailViewController viewDidLoad];
}
#end
MasterViewController.m
#import "MasterViewController.h"
#interface MasterViewController ()
#end
#implementation MasterViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
UITableView *table = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 100, 1004) style:UITableViewStylePlain];
table.dataSource = self;
table.delegate = self;
[self.view addSubview:table];
}
#end
DetailViewController.m
#import "DetailViewController.h"
#interface DetailViewController ()
#end
#implementation DetailViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
UIView *uiview = [[UIView alloc] initWithFrame:CGRectMake(100, 0, 668, 1004)];
[self.view addSubview:uiview];
}
#end
What am I not understanding?
Thanks so much in advance for your wisdom!
P.S. It's worth noting why I'm not using the UISplitViewController. My app is currently designed so that the root view is not split view. The root view of my app will cause a split view to be pushed on to the nav stack. The problem with this is that the UISplitViewController is designed to be the root view of an app and Apple's docs specifically say that if you use a UISplitViewController that it needs to be the root view. Therefor, I'm implementing my own split view and manually managing the views.
Maybe thinking about showing your root view in a different way could help you. e.g like this: using a UISplitViewController as root view and present a modal view on top of it with your current root view. So you use your current root view and the UISplitViewController.
you might wanna try MGSplitViewController which is also based on UIViewController.. and allows push..MGSplitViewController
Other xib's auto-load fine, but not this one.
When I push this viewcontroller, initWithNibName, loadView, viewDidLoad, and viewWillAppear are called fine, but the view (and all self.xxx objects in #interface) are nil in all these methods, and I am left with an empty window under the navigationbar.
SettingsMain *newVC=[[SettingsMain alloc] initWithNibName:#"SettingsMain" bundle:nil];
[self.navigationController pushViewController:newVC animated:YES];
I was wondering if I can force setting self.view to what's in the .xib, in loadView or initWithNibName, so that all the outlets etc are initalized.
The viewcontroller has the standard code,
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
The problem is that when viewDidLoad is fired, self.view is nil.
my app starts with a tab bar controller which have 5 tabs. At start the first one in presented with its name but the other four don't have a name until I click on them. Then the name appears depending which language the user has.
How can I set the name of the tabs before the tab bar appears?
I am using storyboard. Is there a way to set title at the tab bar programmatically when all the rest is done with storyboard? I tried in the AppDelegate something like [FirstViewController setTitle:NSLocalizedString(#"Titel1", nil)];
But I got an error that there is no class method for selector setTitle.
Thanks.
I had the same problem today. I'm using storyboard too. In my case i used the following way.
I've created a new "Objective-C class" with the name
"MainTabBarViewController" as a subclass of "UITabBarController".
In my storyboard in "identity inspector" i changed "Custom class" to "MainTabBarViewController".
In the method "viewDidLoad" in "MainTabBarViewController" i added:
[[self.viewControllers objectAtIndex:0] setTitle:NSLocalizedString(#"home", nil)];
[[self.viewControllers objectAtIndex:1] setTitle:NSLocalizedString(#"statistics", nil)];
[[self.viewControllers objectAtIndex:2] setTitle:NSLocalizedString(#"settings", nil)];
[[self.viewControllers objectAtIndex:3] setTitle:NSLocalizedString(#"info", nil)];
I guess it is not the perferct way, but for me it works perfect.
I had a configuration with two tabs like this:
MainTabBarController : UITabBarController
+- MessagesNavigationController : UINavigationController
+- ContactsNavigationController : UINavigationController
In a configuration with Storyboard and ARC I overrode the initWithCoder: selector in the custom classes of my UITabBarController view controllers (in this case ContactsNavigationController) and initialized the tabBarItem.title there like this:
#implementation ContactsNavigationController
...
- (id)initWithCoder:(NSCoder *)decoder
{
self = [super initWithCoder:decoder];
if (self) {
self.tabBarItem.title = NSLocalizedString(#"Contacts", nil);
}
return self;
}
When using storyboards the iOS calls (id)initWithCoder: instead of -(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil when the storyboard view controller is initialized during UITabBarController launch. Also note that viewDidLoad doesn't get called until the view controller tab is selected from the tab bar.
In the app delegate, where you are creating the view controllers, set the title property here (rather than in viewDidLoad), for example:
vc1 = [[VC1 alloc] init];
vc1.title = #"List";
vc2 = [[VC2 alloc] init];
vc2.title = #"Map";
tabBarController.viewControllers = [[NSArray alloc] initWithObjects:vc1, vc2, nil];
If you take a look at the FirstViewController created by Xcode using the template Tab-Bar application based in the - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil method you can see something like this:
if (self) {
//check your language
self.title = NSLocalizedString(#"First", #"First");
self.tabBarItem.image = [UIImage imageNamed:#"first"];
}
So you have to check for your language and then set the title property, this will set the title on the tab bar and in the navigation bar.
Try this, in every view u have to use this method
Suppose this is you first view
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(#"homepage", #"homepage");
[self.tabBarItem setTag:0];
self.tabBarItem.image = [UIImage imageNamed:#"homepage"];
}
return self;
}
In you app delegate class write this code to add UITabBarController
self.tabBarController = [[[UITabBarController alloc] init] autorelease];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1, viewController2,viewController3,viewController4,viewController5, nil];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
Add above code in
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {}
I've got a UINavigationController that has a UITableViewController as it's root view. The UINavigationController is inside a UITabBarController.
In the UITableViewController (*viewOne), if I click a cell a the following code runs
UIViewController *newView = [[UIViewController alloc] initWithNibName:#"newView" bundle:nil];
[self.navigationController pushViewController:newView animated:YES];
[newView release];
Then, inside of newView is:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
NSLog(#"%#", self.navigationController);
}
return self;
}
The logs have:
[8947:207] (null)
And if I try to push a new view controller to the navigationController, nothing happens. Any clues?
I've figured it out.
In my application delegate, I've added a new property:
UINavigationController *profileNavigationController;
#property (nonatomic, retain) IBOutlet UINavigationController *profileNavigationController;
And in IB, I've connected the profileNavigationController from the app delegate to Navigation Controller.
And now, when pushing new views, I call:
StartDateSelectorViewController *startDateSelectorViewController = [[StartDateSelectorViewController alloc] initWithNibName:#"StartDateSelectorView" bundle:nil];
Strength_EngineAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
[delegate.profileNavigationController pushViewController:startDateSelectorViewController animated:YES ];
I have a uiviewcontroller with two properties: trackName and playerObject. PlayerObject also has a trackName property. I call this uiviewcontroller from my main uiviewController with this code:
SecondaryViewController *nextViewController = [[SecondaryViewController alloc] initWithNibName:#"SecondaryViewController" bundle:nil];
NSString *trackName = #"a track";
nextViewController.trackName = trackName;
[self.navigationController pushViewController:nextViewController animated:YES];
[nextViewController release];
In SecondaryViewController I override the initwithnibname method to set the trackName of the playerObject. I do this with this code:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
playerObject.trackName = trackName;
}
playerObject.trackName = trackName;
return self;
}
Finally my playerObject has all of the view data the SecondaryViewController will need. It looks like:
- (void)awakeFromNib{
NSString *s = trackName;
//more code relevant to the the view controller
}
When I debug, the trackName string in the playerObject is nil. I assume I'm doing something wrong. How can I have this value populated with the trackName I originally passed in the main uiview controller?
It seems like when you are initing the viewController the playerObject variable has not yet been set, could this be possible?
This can sometimes happen when you override initWithNibName:bundle:.
Instead use viewDidLoad to do setup. Apple guarantees all required setup is performed before this method is called (not the case with initWithNibName:bundle:).