This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
XCode 4.5.1, Application windows are expected to have a root view controller at the end of application launch
I'm a total noob in IOS app developing.
I use Xcode 4.5.1 with no storyboard.
I'm upgrading an IOS 4 app because it fails to run correctly on IOS 6 devices.
main view containing a question and five answers run once and stops there after user commit by pressing a button with the wanted answer, it should then reload itself with a new question and a new set of questions.
I get the infamous "Application windows are expected to have a root view controller at the end of application launch" in log output.
I've read and tried all comments and solutions in 7520971 but to no avail... still getting error and it seems to prevent me to load the view correctly.
here's what in my appDelegate.h
/*
* AnimViewAppDelegate.h
* AnimView
*
* Created by Administrateur local on 11-01-19.
* Copyright 2011 __MyCompanyName__. All rights reserved.
*
*/
#import <UIKit/UIKit.h>
#import "RootNavigationController.h"
#interface PPScaleAppDelegate : NSObject <UIScrollViewDelegate> {
UIWindow *window;
RootNavigationController *RootNavigationViewController;
}
#property (nonatomic, retain) UIWindow *window;
#property (nonatomic, retain) RootNavigationController *RootNavigationViewController;
#end
my appDelegate.m
//
// AnimViewAppDelegate.m
// AnimView
//
// Created by Administrateur local on 11-01-19.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import "PPScaleAppDelegate.h"
#import "QuestionView.h"
#implementation PPScaleAppDelegate
#synthesize window;
#synthesize RootNavigationViewController;
//- (void)applicationDidFinishLaunching:(UIApplication *)application {
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//Create the main screen
//CGRect frame = [[UIScreen mainScreen] bounds];
//self.window = [[UIWindow alloc] initWithFrame:frame];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; //2012
//Create the main view controller
RootNavigationViewController = [[RootNavigationController alloc] initWithNibName:NULL bundle:NULL];
//[window addSubview:RootNavigationViewController.view];
[self.window setRootViewController:RootNavigationViewController];
//Show the main window
[self.window makeKeyAndVisible];
return YES;
}
- (void)dealloc {
[window release];
[super dealloc];
}
#end
.h
//
// RootNavigationController.h
// IPhonePPS
//
// Created by Administrateur local on 11-02-11.
// Copyright 2011 Le Groupe CDGI Inc. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "QuestionView.h"
#import "ResultView.h"
#import "ResultTableView.h"
#interface RootNavigationController : UINavigationController {
QuestionView *QuestionViewController;
ResultView *ResultViewController;
ResultTableView *ResultTableViewController;
}
#property(nonatomic, assign) QuestionView *QuestionViewController;
#property(nonatomic, assign) ResultView *ResultViewController;
#property(nonatomic, assign) ResultTableView *ResultTableViewController;
-(void)switchToResultMode:(QuestionPath *)QuestionPath;
-(void)switchToResultTableMode;
-(void)switchBack:(BOOL)Reset;
#end
.m
//
// RootNavigationController.m
// IPhonePPS
//
// Created by Administrateur local on 11-02-11.
// Copyright 2011 Le Groupe CDGI Inc. All rights reserved.
//
#import "RootNavigationController.h"
#implementation RootNavigationController
#synthesize QuestionViewController, ResultViewController, ResultTableViewController;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Initialization code.
QuestionViewController = [[QuestionView alloc] initWithNibName:NULL bundle:NULL];
ResultViewController = [[ResultView alloc] initWithNibName:NULL bundle:NULL];
ResultTableViewController = [[ResultTableView alloc] initWithNibName:NULL bundle:NULL];
//Set the navigation bar hidden
[self setNavigationBarHidden:YES];
//Push the question view on the stack
[self pushViewController:self.QuestionViewController animated:YES];
}
return self;
}
- (void)dealloc {
[super dealloc];
}
-(void)switchToResultMode:(QuestionPath *)QuestionPath {
[self pushViewController:ResultViewController animated:YES];
[ResultViewController setQuestionPath:QuestionPath];
}
-(void)switchToResultTableMode {
[self pushViewController:ResultTableViewController animated:YES];
}
-(void)switchBack:(BOOL)Reset{
if(Reset){
if([self.viewControllers count] == 3){
[self popToRootViewControllerAnimated:YES];
}else {
[self popViewControllerAnimated:YES];
}
[QuestionViewController resetAnswers];
}else {
[self popViewControllerAnimated:YES];
}
}
//-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
// if([self visibleViewController] == self.ResultTableViewController || toInterfaceOrientation == UIInterfaceOrientationPortrait){
// return YES;
// }else {
// return NO;
// }
//}
- (BOOL) shouldAutorotate {
return YES;
}
-(NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAll;
}
#end
spent two complete days trying to debug this but I give up and would really appreciate your help with this issue
PR
It would be better to just use [[alloc] init] if you don't have a nib for your navigation controller. Also, your navigation controller should be initialized with its own rootViewcontroller. I don't know which one you want to be first, but it should look something like this:
MyFirstViewControllerClass *rootVC = [MyFirstViewControllerClass alloc] initWithNibName:#"MyFirstViewController" bundle:nil];
RootNavigationController *nav = [[RootNavigationController alloc]initWithRootViewController:rootVC];
self.window.rootViewController = nav;
You're calling [self.window setRootViewController:RootNavigationViewController]; Notice - setRootViewController. It wants a viewController. Your RootNavigationViewController is a NavigationController as referenced here #interface RootNavigationController : UINavigationController not a viewController.
It looks like you should do something like this
RootNavigationViewController = [[RootNavigationController alloc] initWithNibName:NULL bundle:NULL];
[window makeKeyAndVisible];
[window addSubview:RootNavigationViewController.view];
(referenced from Programmatically build / navigate a Navigation Controller)
I'm not sure if using
[self pushViewController:self.QuestionViewController animated:YES];
in the RootNavigationViewController is the same as doing something like this
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
But that should point you in a good direction to debug your issue.
You should init your RootNavigationController with a rootViewController first :
[RootNavigationController initWithRootViewcontroller:QuestionViewController];
You can find this from the UINavigationController reference :
Because the UINavigationController class inherits from the
UIViewController class, navigation controllers have their own view
that is accessible through the view property. When deploying a
navigation interface, you must install this view as the root of
whatever view hierarchy you are creating.
For instance, in -(void)switchBack:(BOOL)Reset; you popToRootViewController without even having set it.
Related
I had Implemented MFSideMenu in my Application to display left side slide in-out menu.Now I would like to recognise swipe in and swipe out (i.e. Sidemenu open or closed status)by creating delegate method in ThirdParty class MFSideMenuContainerViewController.h as
#import <UIKit/UIKit.h>
#import "MFSideMenuShadow.h"
#class MFSideMenuContainerViewController;
#protocol MFSideMenuContainerViewControllerViewDelegate <NSObject> //define delegate protocol
- (void)swipedLeftSidemenu:(BOOL)isOpen; //define delegate method to be implemented within another class
#end //end protocol
#interface MFSideMenuContainerViewController : UIViewController<UIGestureRecognizerDelegate>
//custom delegate property
#property (nonatomic, weak) id <MFSideMenuContainerViewControllerViewDelegate> delegate1;
#end
and then call delegate method from below method of MFSideMenuContainerViewController.m
- (void)openLeftSideMenuCompletion:(void (^)(void))completion
{
if(!self.leftMenuViewController) return;
//call as below
[self.delegate1 swipedLeftSidemenu:YES];
//below is default thirdparty implementation
[self.menuContainerView bringSubviewToFront:[self.leftMenuViewController view]];
[self setCenterViewControllerOffset:self.leftMenuWidth animated:YES completion:completion];
}
Delegate method used in another viewcontroller class to detect side menu is open or closed for that I had implemented below code
in DemoViewController.h file
#import "MFSideMenuContainerViewController.h"
#interface DemoViewController : UIViewController <ContactViewDelegate,MFSideMenuContainerViewControllerViewDelegate>
in DemoViewController.m file
- (void)viewDidLoad
{
[super viewDidLoad];
MFSideMenuContainerViewController *vc2 = [[MFSideMenuContainerViewController alloc] init];
vc2.delegate1 = self;
}
//DelegateMethod Implementation
-(void)swipedLeftSidemenu:(BOOL)isOpen
{
if(isOpen)
{
// code is here if side menu is open by swiping right
}
else
{
// code is here if side menu is closed by swiping left
}
}
Now I having issue is above method in DemoViewController.m file is never called although sidemenu can be swiped left or right.Can any one guide how I can detect side menu is open or close from DemoViewController class? Or Why this method is never called ?
My appdelegate.m files having below code only
#interface AppDelegate ()
#end
#implementation AppDelegate
- (DemoViewController *)demoController
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
DemoViewController *demoController = [storyboard instantiateViewControllerWithIdentifier:#"DemoViewController"];
return demoController;
}
- (UINavigationController *)navigationController
{
return [[UINavigationController alloc]
initWithRootViewController:[self demoController]];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
SideMenuViewController *leftMenuViewController = [storyboard instantiateViewControllerWithIdentifier:#"SideMenuViewController"];
MFSideMenuContainerViewController *container = [MFSideMenuContainerViewController
containerWithCenterViewController:[self navigationController]
leftMenuViewController:leftMenuViewController
rightMenuViewController:nil];
self.window.rootViewController = container;
[self.window makeKeyAndVisible];
return YES;
}
Update your code In your AppDelegate.h file
#property (strong, nonatomic) UIWindow *window;
#property(strong,nonatomic)ViewController *viewController;
#property(strong,nonatomic)LeftSideViewController *leftSideViewController;
#property(strong,nonatomic)MFSideMenuContainerViewController *container;
#property(strong,nonatomic)UINavigationController *navigationController;
#end
and in your AppDelegate.m file update your code
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.container = [MFSideMenuContainerViewController containerWithCenterViewController:self.navigationController leftMenuViewController:_leftSideViewController rightMenuViewController:nil];
self.window setRootViewController:_container];
[self.window makeKeyAndVisible];
return YES;
}
Instead of delegate method I had replaced it with NotoficationCenter Observer method and that code is as below :
STEP-1
in ThirdParty class MFSideMenuContainerViewController.m as
- (void)openLeftSideMenuCompletion:(void (^)(void))completion
{
if(!self.leftMenuViewController) return;
NSDictionary* userInfo = #{#"isOpen": #"1"};
[[NSNotificationCenter defaultCenter] postNotificationName:#"swipeClassDelegateMethod" object:nil userInfo:userInfo];
//below is default thirdparty implementation
[self.menuContainerView bringSubviewToFront:[self.leftMenuViewController view]];
[self setCenterViewControllerOffset:self.leftMenuWidth animated:YES completion:completion];
}
STEP-2 : then I called below code from my DemoViewController.m file viewDidLoad method
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(swipeClassDelegateMethod:)name:#"swipeClassDelegateMethod" object:nil];
STEP-3 : Finally I implemented this function with necessary code as below in same DemoViewController.m class
-(void)swipeClassDelegateMethod:(NSNotification*)notification
{
}
im a beginner and trying to figure out how to work with nib properly.
I have a HomeViewController.h:
#import <UIKit/UIKit.h>
#import "StackTableViewController.h"
#interface HomeViewController : UIViewController
#property (strong, nonatomic) StackTableViewController *stackViewController;
- (IBAction)goToStack:(id)sender;
#end
HomeViewController.m:
#import "HomeViewController.h"
#interface HomeViewController ()
#end
#implementation HomeViewController
- (id)init {
self = [super initWithNibName:#"HomeViewController" bundle:nil];
if (self) {
//
_stackViewController = [[StackTableViewController alloc]init];
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)goToStack:(id)sender {
//[self.navigationController showViewController:_stackViewController sender:self];
[self presentViewController:_stackViewController animated:YES completion:nil];
}
As you can see I'm modelling from the HomeViewController to StackTableViewController...
Now it works ok, but I want that StackTableViewController will be embedded in NavigationController...that I can put a cancel button in the top.
This is my StackTableViewController.m:
#import "StackTableViewController.h"
#interface StackTableViewController ()
#property (strong, nonatomic) UINavigationController *navBar;
#end
#implementation StackTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
#warning Potentially incomplete method implementation.
// Return the number of sections.
return 0;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
#warning Incomplete method implementation.
// Return the number of rows in the section.
return 0;
}
What should I add to the viewDidLoad method that will embed the navBar in the tableview?
tnx
There is not need to declare StackTableViewController as a property of HomeViewController, just modify goToStack like so:
- (IBAction)goToStack:(id)sender {
StackTableViewController *stackViewController = [[StackTableViewController alloc] init]; // shouldnt this get loaded from a NIB though???
[self presentViewController:stackViewController animated:YES completion:nil];
}
About youer issue with UINavigationController, depending on your setup the UINavigationController is the base for a certain navigation stack within your app, so, if you're just building a simple app without a tab bar or another more complex interface, your UINavigationController might be the rootViewController of your application's main UIWindow (a property of your AppDelegate).
So, what you will have to do to get this setup to work is in application:didFinishLaunchinWithOptions of your AppDelegate, set the application's root window:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
HomeViewController *homeViewController = [[HomeViewController alloc] initWithNibName:#"HomeViewController" bundle:nil]; // I assume you have a NIB file called HomeViewController
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:homeViewController];
self.window.rootViewController = navigationController;
return YES;
}
This will have the effect that the HomeViewController that you will see on application startup, is embedded within an instance of UINavigationController, which again is the rootViewController of your whole application.
Then again, you can modify goToStack to use this instance of UINavigationController instead of showing stackViewController modally:
- (IBAction)goToStack:(id)sender {
StackTableViewController *stackViewController = [[StackTableViewController alloc] init]; // shouldnt this get loaded from a NIB though???
[self.navigationController pushViewController:stackViewController animated:YES];
}
You can use self.navigationController here because homeViewController is embedded in a UINavigaitonController, so iOS will set this property for you.
Hope that helps! :)
Update:
If you don't want to have your HomeViewController embedded within the UINavigationController, just modify goToStack like so:
- (IBAction)goToStack:(id)sender {
StackTableViewController *stackViewController = [[StackTableViewController alloc] init]; // shouldnt this get loaded from a NIB though???
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:stackViewController];
[self presentViewController:navigationController animated:YES completion:nil];
}
I'm trying to implement my own custom UIWindow class. It's named SNWindow. I read that you have to implement your own getter method, and that's what I did but it never get's past "Point 1". It's infinitely logging "Point 1", showing a black screen on the iPhone.
AppDelegate.h
#import <UIKit/UIKit.h>
#import "SNWindow.h"
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) SNWindow *window;
- (SNWindow *)window;
#end
AppDelegate.m
...
- (SNWindow *)window
{
NSLog(#"Point 1");
//
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
//
UIViewController *viewController = [storyboard instantiateInitialViewController];
//
_window = [[SNWindow alloc] init];
_window.rootViewController = viewController;
NSLog(#"Point 2");
return _window;
}
Any ideas on how to fix it?
Do not type the window property as SNWindow; type it as UIWindow, the normal way. Your code, in your App Delegate class, then needs to look like this:
- (UIWindow*) window {
UIWindow* w = self->_window;
if (!w) {
w = [[SNWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self->_window = w;
}
return w;
}
The rest of the App Delegate, such as application:didFinishLaunching..., should just go ahead and do what it would normally do (which might be no more than return YES).
I created a brand new project and created a new view controller with a button in the view.
I am adding the view in application:didFinishLaunchingWithOptions
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
BOOL introDisplayed = [[NSUserDefaults standardUserDefaults] boolForKey:kIntroScreenSeenByUser];
if(introDisplayed)
{
}
else
{
IntroView *introView = [[IntroView alloc] initWithNibName:#"IntroView" bundle:nil];
[self.window addSubview:introView.view];
}
[self.window makeKeyAndVisible];
return YES;
}
.h file
#interface IntroView : UIViewController
#property (weak, nonatomic) IBOutlet UIButton *clickMe;
- (IBAction)clicked:(id)sender;
#end
.m file
#import "IntroView.h"
#interface IntroView ()
#end
#implementation IntroView
#synthesize clickMe;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)viewDidUnload
{
[self setClickMe:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (IBAction)clicked:(id)sender {
NSLog(#"clicked");
}
#end
Clicking on the button results in a EXC_BAD_ACCESS(code=2 error. Any ideas? I am using ARC.
Thanks
UPDATE
Created a public property on the application delegate called "introViewController" and changed the application:didFinishLaunchingWithOptions
#synthesize introViewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
BOOL introDisplayed = [[NSUserDefaults standardUserDefaults] boolForKey:kIntroScreenSeenByUser];
introViewController = [[IntroView alloc] initWithNibName:#"IntroView" bundle:nil];
if(introDisplayed)
{
}
else
{
[self.window addSubview:introViewController.view];
}
[self.window makeKeyAndVisible];
return YES;
}
This solved the error.
You're creating your IntroView controller, and adding it's view as a subview, but the controller itself is released. I don't think that adding the view controller's view (and then letting ARC discard the controller itself) is an acceptable way to create a view.
Perhaps you could make the IntroView view controller a property of the app delegate class and therefore it won't be released by ARC.
Personally, I don't monkey around with the app delegate's creation of the views and controllers, but rather I let my target settings and my NIBs dictate that. I presume you're doing this because you want to have some intro screen. If I wanted an screen, I'd have my main view controller go ahead and present whatever intro I want. That way when the intro is dismissed (or popped off, depending upon whether you pushed or presented modally), my main view controller is still at the top (and useful methods like popToRootViewController work perfectly).
I have a file named MMAppDelegate.m:
#import "MMAppDelegate.h"
#implementation MMAppDelegate
#synthesize window;
#synthesize viewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
viewController = [[MainViewController alloc] init];
[window addSubview:viewController.view];
// Override point for customization after application launch.
[window makeKeyAndVisible];
return YES;
}
//and more standard methods
MMAppDelegate.h:
#import <UIKit/UIKit.h>
#import "MainViewController.h"
#interface MMAppDelegate : UIResponder <UIApplicationDelegate> {
UIWindow *window;
MainViewController *viewController;
}
#property (nonatomic, retain) UIWindow *window;
#property (nonatomic, retain) MainViewController *viewController;
#end
MainViewController.m:
#import "MainViewController.h"
#implementation MainViewController
- (void)viewDidLoad {
NSLog(#"view did load main view controller");
[super viewDidLoad];
self.view.backgroundColor = [UIColor redColor];
}
#end
And yet when I run the program, I get a black screen, and the output:
2012-02-12 15:44:48.160 MoreMost[44076:f803] view did load main view controller
2012-02-12 15:44:48.163 MoreMost[44076:f803] Applications are expected to have a root view controller at the end of application launch
What is the problem?
Change this line:
[window addSubview:viewController.view];
to this:
window.rootViewController = viewController;
And you'll need to create the window, like this:
window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
You don't need/want to add the view controller's view as a subview. You want to make your controller the root view controller and iOS will take care of the rest:
window.rootViewController = viewController;
That is, as of iOS 4. (Not sure the answer if you're going back earlier than that.)
You also need to create the window before you use it. Something like
window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
Not sure if you aren't or if you just didn't show it ...