I am currently running the following code as part of a simple test iPad program. I've declared "viewController" as a property. In all other examples I've seen involving subviews, I've been required to alloc and init the viewController, but here it works fine. Any ideas?
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Why does this work without allocating or initializing viewController?
[self.window addSubview:viewController.view];
[self.window makeKeyAndVisible];
return YES;
}
This looks like the typical boilerplate code Apple supplies with the iOS templates. In these projects the viewController is defined in the MainWindow NIB. This NIB is loaded very early in the process of starting the app. The viewController is allocated in the NIB loading process, and initWithNibName:bundle: is then called. The NIB loading process then connects the initialized object to the view controller's IBOutlet of the app delegate.
Related
I had a class category that adds some methods to UIViewController. I needed to add some instance variables to the category, so I turned it into a custom UIViewController subclass, and added the instance variables. I then turned the UIViewController I was displaying into an instance of the new subclass.
Now I'm having trouble loading the new UIViewController when the application loads. I load the view controller from a nib in my AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
self.viewController = [[ATFIPresentationViewController alloc] initWithNibName:#"ViewController_iPhone" bundle:nil];
} else {
self.viewController = [[ATFIPresentationViewController alloc] initWithNibName:#"ViewController_iPad" bundle:nil];
}
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible]; //Crashes Here
return YES;
}
After doing so, an exception is thrown when I call makeKeyAndVisible on my application's window:
Terminating app due to uncaught exception 'NSUnknownKeyException', reason:
'[<ATFIPresentationViewController 0x6c497d0> setValue:forUndefinedKey:]:
this class is not key value coding-compliant for the key basicPicker.'
Where basicPicker is an IBOutlet to a UITextField. This is happening for every IBOutlet I've defined in my viewController. Why would making my viewController a subclass of my subclass of UIViewController, prevent anything loading from my nib? The "Files Owner" in the nib is ViewController, not ATFIPresentationViewController.
EDIT: Well, I got tired of trying to get this to work the "proper" and less typing heavy way. I got it to work by turning the extension into an NSObject, and pass the UIViewController to it. I posted what I was using this for on gitHub if anyone wants to take a look.
That error is occurring because your nib is trying to set a value onto an instance of a class that doesn't have a property by the name basicPicker. This is a solid indication that you're sending messages to the wrong type of object.
You need set the class of your File's Owner in your nib files to be the new UIViewController subclass you have created and not just the default UIViewController. Select File's Owner in your nib and you can change it in the right panel 'Utilities' third tab named Identity Inspector in Xcode, right at the top.
I'm new to Storyboarding in objective c and I need to call method from UIVIewController. Before Storyboarding I was initializing UIViewController in AppDelegate or just assigning pointer there, and then simply call method from any class, accessing AppDelegate properties. How to do It in Storyboarding, If there are no UIViewController initializing by myself? My app is UITabBar application if it does matter.
You can get the root view controller of your storyboard from your app delegate. For example:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UITabbarController *tbc = (UITabbarController *)self.window.rootViewController;
// Do any setup you want to here
// You aren't setting up the controller - just accessing the one that has been set up for you by the storyboard
return YES;
}
If you want to have this method available from any class you can keep doing the same. Place in in your AppDelegate and then just retrieve the shared instance on the controller you want to use it from. (all your application has access to your appdelegate) so just import the header of the app delegate, create a new instance of your specific appdelegatename class, and call the shared delegate. then you can use the method as if that class would have it.
Additionaly you can use something like this
#import "AppDelegate.h"
#define appDelegate (AppDelegate *) [[UIApplication sharedApplication] delegate]
IF you want to call a method from ANY of your viewcontrollers which are specified in the storyboard you can do it by referencing their identifier:
PreviewViewController *tmp = [[self storyboard] instantiateViewControllerWithIdentifier:#"PreviewViewController"];
I just created an empty iOS project and added a UIViewController with a nib file. This should load my main view.
How do I tell my application to load a certain UIViewController as main view? Do I have to set it on the app delegate or somewhere in xcode?
In your app delegate have a variable for the controller....
MyViewController myController;
Then you want...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
myController = [[MYViewController alloc] initWithNibName:#"MyViewController" bundle:nil];
[self.window addSubview:myController.view];
[self.window makeKeyAndVisible];
return YES;
}
You can also hook this up via Interface Builder, but the above is how you would do it in code.
Through this question I would like to know if I understand well the notion of Root View Controller.
In iOS application, the Root View Controller (RVC) is the controller whose view gets added to the UIWindow application at startup, isn't true?
[window addSubview:rvcController.View];
[window makeKeyAndVisible];
Now, an UIWindow has also a rootViewController property. When running the previous snippet of code, does that property gets populated with the rvcController or do I have to set it explicitly?
Then, in a UINavigationController it is possible to set a RVC that is different from the previous RVC set for the entry point.
In this case, the first time I add a controller to the navigationController stack (pushing a new controller on it), does the framework set that controller as the RVC for the navigationController or do I have to set it explicitly through initWithRootViewController method?
Ya.. when I began iPhone dev.. the rootViewController thing threw me for a loop too. But it’s really straight forward.
when the app starts, I create a UIWindow object in my app delegate class. Also, in that class, I have a property of type UIWindow called window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UIWindow *w = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];
self.window=w;
[w release];
// other code here...
}
I then create a UIViewController whose view will be the first view in the window hierarchy, this could be called the "root view controller".
The confusing part is...that often we create a UINavigationController as the "root view controller" and that navigation controller has an init method that asks for a "RootViewController", which is the first viewcontroller it will place on its stack.
So, the window gets a "root view controller", which is the UINavigationController, which also has a RootViewController, which is the first view controller you want to show.
once you sort that out, its all makes sense.. I think :-)
here is some code that does it all.. (taken from a project I have open in front of me)
//called with the app first loads and runs.. does not fire on restarts while that app was in memory
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//create the base window.. an ios thing
UIWindow *w = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];
self.window=w;
[w release];
// this is the home page from the user's perspective
//the UINavController wraps around the MainViewController, or better said, the MainViewController is the root view controller
MainViewController *vc = [[MainViewController alloc]init];
UINavigationController *nc = [[UINavigationController alloc]initWithRootViewController:vc];
self.navigationController=nc; // I have a property on the app delegate that references the root view controller, which is my navigation controller.
[nc release];
[vc release];
//show them
[self.window addSubview:nc.view];
[self.window makeKeyAndVisible];
return YES;
}
Now, an UIWindow has also a rootViewController property. When running the previous snippet of code, does that property gets populated with the rvcController or do I have to set it explicity?
You have to set it explicitly, and if you do, you can remove the addSubview line, because that's handled automatically when you set a root view controller.
Then, in a UINavigationController it is possible to set a RVC that is different from the previous RVC set for the entry point.
Of course, a navigation controller's root view controller has nothing to do with that of the window.
In this case, the first time I add a controller to the navigationController stack (pushing a new controller on it), does the framework set that controller as the RVC for the navigationController or do I have to set it explicity through initWithRootViewController method?
initWithRootViewController is just a shortcut for initializing an empty navigation controller and pushing the first (root) view controller onto the stack. Note that rootViewController is not a property of UINavigationController, you would access it via [navController.viewControllers objectAtIndex:0].
firstly you can create A empty project in Xcode. after you add the new file on objectivec class view controller with xiv. now you can add to this code in appdeligate.m
and set the rootviewcontroller in appdeligate
NOTE:- ViewController.h import to the appdeligate.m
-(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];
ViewController *viewcontroller =[[ViewController alloc]initWithNibName:#"ViewController" bundle:nil];
self.window.rootViewController= viewcontroller;
[self.window makeKeyAndVisible];
return YES;
}
-(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];
ViewController *viewcontroller =[[ViewController alloc]initWithNibName:#"ViewController" bundle:nil];
self.window.rootViewController= viewcontroller;
[self.window makeKeyAndVisible];
return YES;
}
i made a simple application using view based template.and i put only nslog inside view didload method in viewController file and also inside applicationDidFinishLaunch method (in appDelegate )to checked which class file called first.
after the run i got: viewController Run first and then appdelegate ..but i think appdelegate should first then other's called according to the need ... plz give me the proper reasion.
Noted that --i did not call viewController (didnot make object) in my appDelegate(inside application didFinishLaunch) . i am using ios4
If your View Controller is a property of the AppDelegate, similar to the code reference
#interface AppDelegate_Shared : NSObject <UIApplicationDelegate, UIAlertViewDelegate, OMFDataLoadDelegate> {
NSManagedObjectModel *managedObjectModel;
NSManagedObjectContext *managedObjectContext;
NSPersistentStoreCoordinator *persistentStoreCoordinator;
UIWindow *window;
UITabBarController *tabBarController;
}
then it is probably getting allocated by the AppDelegate when it is being allocated. According to the Apple documentation viewDidLoad is run after the view is loaded into memory, which can be a little confusing, since the language can make you believe it's when it's loaded onto the screen.
http://developer.apple.com/iphone/library/documentation/uikit/reference/UIViewController_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40006926-CH3-SW25
Move your NSLog statement to viewDidAppear for the result you were expecting. Here's two sample snippets with the way you should expect the statements to load.
ViewController.m
- (void) viewDidLoad {
NSLog(#"1st - this occurs when appDelegate allocates this object");
}
- (void) viewDidAppear {
NSLog(#"3rd - this should appear after the applicationDidFinishLaunchingStatement");
}
AppDelegate_Shared.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSLog(#"2. Starting AppDelegate_Shared");
[window addSubview:self.tabBarController.view];
[window makeKeyAndVisible];
NSLog(#"4. Leaving AppDelegate_Shared");
return YES;
}
If the initial view hasn't loaded then clearly the application has not finished launching.
The messages are sent in the right order.