ViewWillAppear is never called automatically I have to call them manually. ViewWillDisappear is often called though.
I do not know where to debug this.
I suppose the problem is because I created the application on 4.1 where people have to call viewWillAppear explicitly.
I suppose, because viewWillAppear will be called depending on its relation with window I can check if my viewController has an outlet to window.
How do I do so?
I suspected the problem is somewhere in my delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[Crashlytics startWithAPIKey:#"a08863b514ef09558ba82fec070cc7468fdbeeae"];
if(getenv("NSZombieEnabled") || getenv("NSAutoreleaseFreedObjectCheckEnabled"))
{
NSLog(#"NSZombieEnabled/NSAutoreleaseFreedObjectCheckEnabled enabled!");
}
[self.window addSubview:self.navController.view]; //This seem to be the problem. I should have specified the viewController and not the view
[self.navController pushViewController:self.MainBadgerApplication animated:YES];
//[cachedProperties singleton].lastAnchor =[cachedProperties currentLocation];
[cachedProperties singleton].currentAnchor=[cachedProperties currentLocation];
self.MainBadgerApplication.selectedIndex=0;
[BNUtilitiesQuick tabBarController:self.MainBadgerApplication didSelectViewController:self.MainBadgerApplication.selectedViewController];
[self.window makeKeyAndVisible];
return YES;
}
I suspected that
[self.window addSubview:self.navController.view]; is the issue.
Also I've heard before ios5 you do have to call viewController explicitly. So should I create a different program for ios5 and ios4 (not like there is any danger in calling viewController twice for my program)
I suspected that [self.window addSubview:self.navController.view]; is the issue.
Probably. You should be doing this instead:
self.window.rootViewController = self.navController;
Just adding the view doesn't put your view controller into the hierarchy properly. See the WWDC 2011 view controller containment video for more information.
Related
I am getting a message within the console when I run my app that says:
2011-11-16 19:17:41.292 Juice[8674:707] Applications are expected to have a root view controller at the end of application launch
I have heard from others that this has to do with the method didFinishLaunchingWithOptions
If anyone has any suggestions for why I am getting this error, it would be much appreciated.
My code for the method:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
[window addSubview:tabBarController.view];
[window makeKeyAndVisible];
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationFade];
return YES;
}
You should replace the
[window addSubview:tabBarController.view];
to
[self.window setRootViewController:tabBarController];
Maybe you built your project with 'Empty Application' and forgot to set the rootViewController in your didFinishLaunchingWithOptions (which exists in your AppDelegate.m).
However, if you build your project with 'Single View Application' or some other type, the project will set the rootViewController via xib by default (which might be a MainWindow.xib in your project).
I had the same problem on iOS 5, after adding a storyboard to an "empty" project. It turns out I had to remove all the lines in AppDelegate.m that set values to self.window.
- (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];
//[self.window makeKeyAndVisible];
return YES;
}
If you have MainWindow.xib, make sure you set Main Interface in Target's summary to MainWindow.
The way I got this error Applications are expected to have a root view controller at the end of application launch to disappear, was to ensure the loadView method in my root view controller was calling [super loadView]. Hope this helps someone.
Try using self.window instead of window (if your setup has window being synthesized with something like #synthesize window=_window;):
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
[self.window addSubview:tabBarController.view];
[self.window makeKeyAndVisible];
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationFade];
return YES;
}
2nd possibility:
In your main.m make sure the last argument is the name of the App Delegate. In your case, it looks like it should be:
retVal = UIApplicationMain(argc, argv, nil, #"JuiceAppDelegate");
Solution:
As #marcus13 said in the comments below.. This was fixed was found in this SO answer: Applications are expected to have a root view controller at the end of application launch - by by moving the UIAlertView methods from -(void)viewDidLoad to -(void)viewDidAppear:(BOOL)animated
Another cause:
I was in IB attaching File Owner to a new small ImageView I'd dragged onto the View. I hadn't called it an IBOutlet in the .h file, so when I ctrl-dragged to it, the new Imageview wasn't listed as a possible connection. The only possibility displayed in the little black box was View. I must have clicked, inadvertently. I made a few changes then ran the program and got the Root Controller error. The fix was reconnecting File Owner to the bottom View in the xib - IB screen.
I just ran into this issue while building a new project from scratch. I added a StoryBoard and build my whole interface, but i did not select a template.
When doing it this way, you have to make sure of 3 main things:
Always select your initial controller (TabBarcontroller or NavigationController) as the initial view in your Storyboard.
Change the code in your Appdelegate.m from this
- (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];
[self.window makeKeyAndVisible];
return YES;
}
to this
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
return YES;
}
Check your [ProjectName]-Info.plist file. If there is no key named "Main storyboard file base name", you have to manually add it and set it's value to the name of your storyboard file (without the extension).
After i did all of these steps, my application ran perfectly.
I also had the same problem. All I got was a black screen. Turns out I had inadvertently removed:
[self.window makeKeyAndVisible];
from my code. Hope this helps someone!
I had two outlets assigned to "view" in the storyboard's root view controller. Right-click on "view controller" and make sure there's only one "view".
I also had the same error while developing an app that uses sqlite Database.
I was showing alertView when the db file transfer failed.
This was a mistake since you cannot show any popovers/alertview/actions without any rootViewController set!
I fixed it by ensuring that any function that creates and shows these alerts/popovers/actionsheets are called after
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
[someObject functionthatDisplayAlerts];
I know this post is old but I ran into this today.
It's because I created a UIAlertView in didFinishLaunchingWithOptions.
Assuming then we should not be doing this because I commented it out and the error went away. I removed my comments and the error came back.
The app doesn't crash, I just get that logged error.
I had the same problem with my App. It appeared when I added another view controller to my project and tried to set it as the root view controller in AppDelegate. I tried several solutions, but none of them could fix the problem. Finally I found the cause: I had two localized versions of the MainWindow.xib file (One for german and another for english localization). So I deleted the english file and reconnected the IBOutlets in MainView.xib. This solved the problem.
I'm not sure if this will help anybody else, but if you have used interface builder to create your mainWindow and have done all the linking between the delegate make sure you don't have the following code within application:didFinishLaunching ...
[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]
I was having the same error until I removed the above line. Hope that helps!
EDIT: Doing the above now has my viewControllers viewDidAppear method being called twice ?
If you are using Storyboard, but created an empty project, you probably forgot to set the Main storyboard to your *.storyboard file in the Summary tab in your project settings. It helped me to solve this problem.
If you are starting from an empty you have to make this addition to your AppDelegate.m file, to "point" the window to the rootViewController (self.window.rootViewController = [[[ViewControllerName alloc] initWithNibName:#"ViewControllerName" bundle:nil] autorelease];)
Like so:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
self.window.rootViewController = [[[ViewControllerName alloc] initWithNibName:#"ViewControllerName" bundle:nil] autorelease];
[self.window makeKeyAndVisible];
return YES;
}
I've been researching this all day but I haven't found anything about the rootViewController in relation to this error message. I know what the problem is but have no idea how to fix it. My problem is that my window.rootViewController is not connected or shows null and I can't figure out what to do. I've tried everything I could think of in code and in IB, but bad things happen whenever I change something. This is the message I get: "Application tried to push a nil view controller on target UINavigationController"
I can see the window.rootViewController from an NSLog statement:
"window.rootViewController : (null)"
of course, everything was working perfectly before upgrading my Xcode to 4.2 and ios5. :)
btw - the view loads but I cannot work any of the buttons, they do not light up at all. And my navigation works fine too.
here is my appDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[DDLog addLogger:[DDTTYLogger sharedInstance]];
NSLog(#"Viewcontroller : %#", self.viewController);
// Set the view controller as the window's root view controller and display.
//self.window.rootViewController = self.viewController;
//do it this way, previous version not supported in ios5 - may need to check version for compatibility
[self.window addSubview:self.viewController.view];
//set up navigation controller
NSLog(#"window.rootViewController : %#", self.window.rootViewController);
navigationController = [[UINavigationController alloc]
initWithRootViewController:self.window.rootViewController];
navigationController.navigationBarHidden = YES;
NSLog(#"navigationController : %#", navigationController);
[window addSubview:navigationController.view];
[window makeKeyAndVisible];
//force this view to be landscape
[application setStatusBarOrientation: UIInterfaceOrientationLandscapeRight animated:NO];
[self.navigationController.view setTransform: CGAffineTransformMakeRotation(M_PI / 2)];
[self.navigationController.view setFrame:CGRectMake(0, 0, 748, 1024)];
[UIView commitAnimations];
return YES;
}
Thank you.
According to the docs:
Discussion
The root view controller provides the content view of the window. Assigning a view controller to this property (either programmatically or using Interface Builder) installs the view controller’s view as the content view of the window. If the window has an existing view hierarchy, the old views are removed before the new ones are installed.
Double check your nib file to make sure it is connect.
Although the "Application tried to push a nil view controller on target UINavigationController" sounds like you maybe losing your VC reference. How is the property set for this? Is it retained?
Here are the docs.
http://developer.apple.com/library/ios/documentation/uikit/reference/UIWindow_Class/UIWindowClassReference/UIWindowClassReference.html#//apple_ref/doc/uid/TP40006817-CH3-SW33
I came across this post here (link below) and it states that you can replace:
[window addSubview: someController.view];
with:
self.window.rootViewController = self.someController;
My Base SDK for All Configurations is set to Latest iOS (currently set to iOS 4.2), however when I try to build the project I get this error: Request for member, 'mainMapView' in something not a structure or union.
Adding it with the commented out addSubview: works fine though.
This is the code in question...
#import "MakeView2AppDelegate.h"
#import "MainMap.h"
#implementation MakeView2AppDelegate
#synthesize window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
MainMap *mainMapView = [[MainMap alloc] initWithNibName:nil bundle:nil];
//[self.window addSubview:mainMapView.view];
self.window.rootViewController = self.mainMapView;
[self.window makeKeyAndVisible];
return YES;
}
self.window.rootViewController vs window addSubview
This is because you're looking for mainMapView as a property of the app delegate. Change that line to:
self.window.rootViewController = mainMapView;
This is assuming that the MapView class inherits from UIViewController, however. Does it?
In your example, you are calling self.mainMapView, but unless mainMapView is a property on the class, this won't work. If you remove the "self." from it, it will work fine.
Since iOS4 this has been the default behaviour in the templates in Xcode4. It's probably better to use addSubview for backwards compatibility as the other method does not work with iPhone OS 3.x
you have not create property for mainMapView.
so you can not write self.mainMapView
you have to use mainMapView.
for more help see this :
Understanding your (Objective-C) self
http://useyourloaf.com/blog/2011/2/8/understanding-your-objective-c-self.html
I was wondering something about the app delegate of my app.
Why can't I release like this :
-(BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
RootViewController *controller = [[RootViewController alloc]
initWithNibName:#"RootViewController"
bundle:[NSBundle mainBundle]];
[self.window addSubview:controller.view];
[controller release]; // Here's my question
[self.window makeKeyAndVisible];
return YES;
}
I was almost sure that -addSubview method increase by 1 my retain count. So why do I have crash when I release my controller ? Why is it working in another class but the delegate ?
Thanks !
The other answers are correct, the UIVIewController is not being retained, what I recommend is setting the UIWindows rootViewController (only available iOS 4.0 and later) property which does retain the controller. If your app supports pre iOS 4.0 then you will need to store controller in an instance variable.
-(BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
RootViewController *controller = [[RootViewController alloc]
initWithNibName:#"RootViewController"
bundle:[NSBundle mainBundle]];
//controller will be retained and view will set for you
window.rootViewController = controller;
[controller release];
[self.window makeKeyAndVisible];
return YES;
}
This line
[self.window addSubview:controller.view];
increases the retain count of controller.view not controller. That's why
[controller release];
creates a problem.
If this is the main window, then you don't need to worry about the memory leak, because the window is active for the entire life of the program, and all memory is purged when it terminates.
addSubView increases the retain count of the view inside of the view controller, that is why the app crashes if you release the controller.
in any case, if you don't release it, you will have a leak. the solution is creating an ivar in your class and assigning to it the view controller (instead of a local variable), then release it in dealloc.
When you add view as subview then view gets retained, not its controller. So when you release controller it gets deallocated and its view - not. As result later view try to send messages to its already deallocated controller and app crashes.
This because you are the unique owner of that controller. You just add its view as a subview of the window. Although the view gets retained by the window's view, the controller not.
So, it will get deallocated and any further use of it will make your app crash.
i have created and ipad application.
i started off with window based application and added 2 view controllers(loginviewcontroller , detailviewcontroler ) . both have their own XIB'S. the added the loginviewcontroller object in in the appdelegate applicationdidfinishlaunch method , i wrote code to move back and forth between 2 views. Here is the code.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
Login *mylogin = [[Loginviewcontroller alloc] init];
[window addSubview:mylogin.view];
//detailview *tv=[[detailviewcontroller alloc] init];
// [window addSubview:tv.view];
[self.window makeKeyAndVisible];
return YES;
}
The problem is that the willrotatetointerfaceorientation method runs only from the loginviewcontroller class even if i am in the detailviewcontroller.
if i add the tickets view to the appdelegate then it runs the willrotatetointerfaceorientation method from detailviewcontroller , so in summary it runs the willrotatetointerfaceorientation method from only the object which was added to appdelegate.
how do i make the 2 view controllers run their respective willrotatetointerfaceorientation methods?
UIViewController has the method
(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
override this method in your both viewcontroller classes(i.e. (loginviewcontroller , detailviewcontroler )
write this code
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
//write your code which you want to during rotation
return Yes;
}
The rotation messages are being sent only to the controller of topmost view. You should forward them manually in appropriate methods.