'NSInvalidArgumentException' when adding UINavigation controller - ios

I am trying to add a static UINavigation bar that will be present on a nearly all ViewControllers in my project. The UINavigation bar will have the same 3 buttons throughout (one opens a side menu, one opens a search, one opens a ViewController to allow settings to be changed.
I have followed several tutorials (none are for Xcode5/iOS7) and these haven't worked for me.
Relevant code of "AppDelegate.m":
#import "AppDelegate.h"
#import "MainViewController.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UINavigationController *navVC = [[UINavigationController alloc] init];
MainViewController *mainVC = [[MainViewController alloc] init];
[navVC setViewControllers:[NSArray arrayWithObject:mainVC]];
[self.window setRootViewController:navVC];
return YES;
}
Running this gives the following error:
'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
MainViewController.m init
#implementation MainViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
Thanks,
Edit:
To Clarify, I am using a storyboard called 'Main', many ViewControllers with the first one being loaded called 'MainVC' which has a custom class called 'MainViewController'. Thanks to #LML the working code for this is now:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main"
bundle: nil];
MainViewController* mainVC = [mainStoryboard instantiateInitialViewController];
UINavigationController *navVC =[[UINavigationController alloc] initWithRootViewController:mainVC];
[self.window setRootViewController:navVC];
[_window makeKeyAndVisible];
return YES;
}

use this because you are using storyboard
-
(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:...{
// set to storyboard on launch
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"iPhoneStoryboard"
bundle: nil];
MainViewController* mainVC = [mainStoryboard instantiateInitialViewController];
UINavigationController *navVC =[[UINavigationController alloc] initWithRootViewController:mainVC];
[self.window setRootViewController:navVC];
[window makeKeyAndVisible];
return YES;
}

Use [[UINavigationController alloc] initWithRootViewController:mainVC].

Try this in your didFinishLaunchingWithOptions method-
MainViewController *mainVC = [MainViewController alloc]initWithNibName:#"MainViewController" bundle:nil];
UINavigationController *navVC =[[UINavigationController alloc] initWithRootViewController:mainVC]; // Change here
[navVC setViewControllers:[NSArray arrayWithObject:mainVC]];
[self.window setRootViewController:navVC];
return YES;

Related

MFSideMenu side Viewcontroller not navigate to Specific view controller in Tabbarcontroller

I am using MFSideMenu in TabBarController In SideMenu i have added UITableview so when i click on cell then it navigate to another view controller but its not navigate to that view controller
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
centerViewController = [storyboard instantiateViewControllerWithIdentifier:#"Tabbarcontroller"];
TabViewController1 *tableView = [storyboard instantiateViewControllerWithIdentifier:#"TabViewController1"];
UINavigationController *nav1 = [[UINavigationController alloc] initWithRootViewController:tableView];
TabViewController2 *tableView2 = [storyboard instantiateViewControllerWithIdentifier:#"TabViewController2"];
UINavigationController *nav2 = [[UINavigationController alloc] initWithRootViewController:tableView2];
centerViewController.viewControllers = #[nav1,nav2];
UIViewController *leftSideMenuViewController = [storyboard instantiateViewControllerWithIdentifier:#"SideViewController"];
container = [MFSideMenuContainerViewController
containerWithCenterViewController:centerViewController
leftMenuViewController:leftSideMenuViewController
rightMenuViewController:nil];
self.window.rootViewController = container;
[self.window makeKeyAndVisible];
return YES;
}
SideMenu.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ViewController3 *objEdit =[self.storyboard instantiateViewControllerWithIdentifier:#"ViewController3"];
AppDelegate *objApp = (AppDelegate *)[[UIApplication sharedApplication]delegate];
UINavigationController *navigationController = (UINavigationController *) objApp.centerViewController.navigationController;
NSLog(#"navigationcontroller :%#",objApp.centerViewController.navigationController);
[navigationController pushViewController:objEdit animated:YES];
[self.menuContainerViewController setMenuState:MFSideMenuStateClosed];
}
objApp.centerViewController is tabbarcontroller, So you need to find out selected view controller from tabor controller first. If you want to push controller in selected tab, You should get Navigationcontroller from SelectedViewCOntroller of tabbarcontroller.
UINavigationController *navigationController = (UINavigationController *) objApp.centerViewController.selectedViewController;
[navigationController pushViewController:objEdit animated:YES];

Choose which ViewController will display initially

I'm trying to select which ViewController the AppDelegate should display based in a NSUserDefaults BOOL. But the HomeViewController does not display.
I'm using Storyboards and I have my own class of UINavigationController.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[FBLoginView class];
[FBProfilePictureView class];
MeuNavigationController *nav = [[MeuNavigationController alloc]init];
if ([NSUD boolForChave:#"firstLogin"]==false) {
ViewController *viewC = [[ViewController alloc]init];
[nav pushViewController:viewC animated:NO];
}else{
HomeViewController *viewP = [[HomeViewController alloc]init];
[nav pushViewController:viewP animated:NO];
}
return YES;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[FBLoginView class];
[FBProfilePictureView class];
UIViewController *controller = nil;
if ([NSUD boolForChave:#"firstLogin"]==false) {
controller = [[ViewController alloc]init];
}else{
controller = [[HomeViewController alloc]init];
}
self.window.rootViewController = [[MenuNavigationController alloc] initWithRootViewController:controller];
[self.window makeKeyAndVisible];
return YES;
}
You noted that you're doing this off of storyboard. You might want to consider making this change as well:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[FBLoginView class];
[FBProfilePictureView class];
// Name of storyboard
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *controller = nil;
if ([NSUD boolForChave:#"firstLogin"]==false) {
controller = [[ViewController alloc]init];
// Set this in the storyboard's identity inspector
controller = [storyboard instantiateViewControllerWithIdentifier:#"ViewController"];
}else{
controller = [storyboard instantiateViewControllerWithIdentifier:#"HomeViewController"];
}
self.window.rootViewController = [[MenuNavigationController alloc] initWithRootViewController:controller];
[self.window makeKeyAndVisible];
return YES;
}
But you ask... Mr. jakenberg, how does one set their unique view controller identifier?
Cheers

Using nibs and storyboards together

From what I have read on the internet, nibs and storyboards are comparable with each other in the same project. Now I am creating a tabbed application and would like to do the following:
Tab 1: constructed with nibs,
Tab 2: constructed with storyboards,
Tab 3: constructed with nibs
Initially I created everything with nibs so in my delegate I was passing from one tab to the next with this code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
UIViewController *viewController1, *viewController2, *viewController3;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
viewController1 = [[[FirstViewController alloc] initWithNibName:#"FirstViewController_iPhone" bundle:nil] autorelease];
viewController2 = [[[SecondViewController alloc] initWithNibName:#"SecondViewController_iPhone" bundle:nil] autorelease];
viewController3 = [[[ThirdViewController alloc] initWithNibName:#"ThirdViewController_iPhone" bundle:nil] autorelease];
} else {
viewController1 = [[[FirstViewController alloc] initWithNibName:#"FirstViewController_iPad" bundle:nil] autorelease];
viewController2 = [[[SecondViewController alloc] initWithNibName:#"SecondViewController_iPad" bundle:nil] autorelease];
viewController3 = [[[ThirdViewController alloc] initWithNibName:#"ThirdViewController_iPad" bundle:nil] autorelease];
}
self.tabBarController = [[[UITabBarController alloc] init] autorelease];
self.tabBarController.viewControllers = #[viewController1, viewController2, viewController3];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
Instead of having the SecondViewController_.xib I need to have the SecondViewController_.storyboard. How do I do this? Can I just change the name "SecondViewController_.nib" to "SecondViewController_.storyboard"? I don't think this would work..
Any help would be very appreciated!!
EDIT:
the code i was using :
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(#"Events", #"Events");
self.tabBarItem.image = [UIImage imageNamed:#"second"];
}
return self; }
You could do what you're suggesting by creating a storyboard and then creating a SecondViewController scene inside it. In code, you would then replace initWithNibName: with calls to storyboardWithName: and instantiateViewControllerWithIdentifier:.
However, since a major feature in storyboards is the ability to tie multiple controllers together and define relationships between them, it's hard to imagine why doing it for one controller would be a good idea.
As Phillip said, just use instantiateViewControllerWithIdentifier.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
UIViewController *viewController1, *viewController2, *viewController3;
UIStoryboard *storyboard;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
viewController1 = [[[FirstViewController alloc] initWithNibName:#"FirstViewController_iPhone" bundle:nil] autorelease];
storyboard = [UIStoryboard storyboardWithName:#"iPhone" bundle:nil];
viewController2 = [storyboard instantiateViewControllerWithIdentifier:#"Second"];
viewController3 = [[[ThirdViewController alloc] initWithNibName:#"ThirdViewController_iPhone" bundle:nil] autorelease];
} else {
viewController1 = [[[FirstViewController alloc] initWithNibName:#"FirstViewController_iPad" bundle:nil] autorelease];
storyboard = [UIStoryboard storyboardWithName:#"iPad" bundle:nil];
viewController2 = [storyboard instantiateViewControllerWithIdentifier:#"Second"];
viewController3 = [[[ThirdViewController alloc] initWithNibName:#"ThirdViewController_iPad" bundle:nil] autorelease];
}
self.tabBarController = [[[UITabBarController alloc] init] autorelease];
self.tabBarController.viewControllers = #[viewController1, viewController2, viewController3];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
This assumes that your storyboards were called iPhone.storyboard and iPad.storyboard, but change the above code to match whatever you call these two storyboards. Furthermore, this again assumes that you defined that scene to bear a "Storyboard ID" of Second (you do that by selecting the view controller in IB and going to the "Identity Inspector") and also that you specified your "custom class" there, too:
For SecondViewController, you should replace you initWithNibName:bundle: method with:
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
self.title = NSLocalizedString(#"Events", #"Events");
self.tabBarItem.image = [UIImage imageNamed:#"second"];
}
return self;
}

How to push Viewcontroller from rootViewController in iOS

I have 2 ViewController. loginViewControl which sets to rootViewControoler :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
loginViewControl = [[LoginTab alloc] init];
self.window.rootViewController = loginViewControl;
[self.window makeKeyAndVisible];
return YES;
}
And I create StatusViewController :
*.h
#interface StatusViewController : UIViewController<UITabBarControllerDelegate>
{
IBOutlet UITabBarController *tabBarController;
IBOutlet UIButton *UploadButton;
IBOutlet UIButton *ConvertorButton;
IBOutlet UIButton *CompletedButton;
}
#property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
#end
Now I want to push StatusViewController from loginViewControl(rootviewcontroller).I used below code but it not work.
- (IBAction)statusButtonClick:(id)sender;
{
StatusViewController *statusView = [[StatusViewController alloc]init];
[self.navigationController pushViewController:statusView animated:YES];
[statusView release];
}
Do you have any suggestions? Thanks in advance
You not setting UINavigationViewcontroller at the didFinishLaunchingWithOptions of Window's RootViewcontroller, We can't Push a UIViewController without UINavigationViewcontroller
So First Set LoginViewController as a RootViewController of UINavigationViewcontroller like Bellow:-
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
loginViewControl = [[YourLoinViewcontroller alloc] initWithNibName:#"YourLoinViewcontroller" bundle:nil];
UINavigationController *objNavigationController=[[UINavigationController alloc]initWithRootViewController:loginViewControl];
self.window.rootViewController = objNavigationController;
[self.window makeKeyAndVisible];
return YES;
}
EDIT
Connect your StatusViewcontroller's view with File owner like bellow:-
your push method like this:-
- (IBAction)statusButtonClick:(id)sender;
{
StatusViewController *statusView = [[StatusViewController alloc]initWithNibName:#"StatusViewController" bundle:nil];
[self.navigationController pushViewController:statusView animated:YES];
}
Unless your login view controller is a navigation controller, self.navigationController in statusButtonClick will return nil and so this won't work.
Maybe you can try:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
loginViewControl = [[LoginTab alloc] init];
self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:loginViewControl];
[self.window makeKeyAndVisible];
return YES;
}
This will enclose a loginViewController in a navigationController which will permit you to push another viewController in the navigationController's stack.
- (IBAction)statusButtonClick:(id)sender; {
// If used StoryBoard
UIStoryboard *story=[UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
StatusViewController *statusView = [story instantiateViewControllerWithIdentifier:#"StatusViewController"];
[self.navigationController pushViewController:statusView animated:YES];
// If used XIB
StatusViewController *statusView = [[StatusViewController alloc]initWithNibName:#"StatusViewController" bundle:nil];
[self.navigationController pushViewController:statusView animated:YES]; }

"Applications are expected to have a root view controller at the end of application launch"

My app was launching fine earlier today and now I'm getting this error
"Applications are expected to have a root view controller at the end of application launch"
I've looked at other threads saying to change my code, but I never changed any code to get to this point.
Delegate.h
#interface halo4AppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate>{
UIWindow *window;
UITabBarController *tabBarController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
#end
Delegate.m
#implementation halo4AppDelegate
#synthesize window;
#synthesize tabBarController;
#pragma mark -
#pragma mark Application lifecycle
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
sleep(3);
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
#pragma mark -
#pragma mark Memory management
- (void)dealloc {
[tabBarController release];
[window release];
[super dealloc];
}
#end
The xib for my FirstViewController is titles FirstView.xib , ext
This is not an error, more like a warning.
In your application delegate there is a method named application:didFinishLaunchingWithOptions: in this method you have to make this line before the end of the method self.window.rootViewController = [Some UIViewController]
again, this is not an error, you can ignore the rootViewController IF you have another way to create this rootViewController.
EDIT
This is what your method should looks like:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
UIViewController *viewController1 = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
UIViewController *viewController2 = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = #[viewController1, viewController2];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}

Resources