Assigning a custom ViewController as the rootViewController of the window - objective-c

Is this a good way to set a custom ViewController as the rootViewController of the window?
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window.rootViewController = [[[CustomViewController alloc]init] autorelease];
[self.window makeKeyAndVisible];
return YES;
}
In most of Apple's examples they first declare a viewController property, and then:
RootViewController* theRVC = [[RootViewController alloc] init];
self.viewController = theRVC;
[theRVC release];
[self.window addSubview:self.rvc.view];
[self.window makeKeyAndVisible];
What is the diference between these two approaches and which is recommended?

The rootViewController property of UIWindow was recently introduced with iOS4. This new method seems to be the recommended approach advocated by Apple. Either approach works but I would stick with the new way of setting the rootViewController property only if you are not targeting early versions of iOS.

Related

Objective c: iOS 13+ programmatically setting initially root view controller

I am trying to set an initial root view controller programmatically using SceneDelegate in iOS 14 (no storyboard at all). I have followed https://medium.com/#sapa.tech/xcode-11-3-remove-storyboard-from-project-6c48c9d11123 to remove storyboard from my app, and have seen many answers to this question in swift in Why is manually setup root view controller showing black screen?, and Set root view controller iOS 13 and iOS 13: Swift - 'Set application root view controller programmatically' does not work. However, I am looking for tips on how to do it in objective C instead. So far, I have this in my scene delegate, where ViewController is the class I am trying to set as the root view controller:
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
UIWindowScene * winscene = [[UIWindowScene alloc]initWithSession:session connectionOptions:connectionOptions];
[self.window setWindowScene:winscene];
ViewController * viewController = [[ViewController alloc]init];
self.window.rootViewController = viewController;
[self.window makeKeyAndVisible];
}
And in my AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
return YES;
}
I have tried to translate the Swift answers I found to objective c but I still end up with a black screen on the simulator. The app builds fine with no error, but I just cannot get the ViewController to show up instead of a black screen. Does anyone know what I am missing?
You're not supposed to create a UIWindowScene yourself, but to use the one given as parameter:
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
self.window = [[UIWindow alloc] initWithWindowScene:(UIWindowScene *)scene];
ViewController * viewController = [[ViewController alloc]init];
self.window.rootViewController = viewController;
[self.window makeKeyAndVisible];
}

Calling a new view: problems "hiding instance variable"

I am trying to call a subview after a button is clicked on my root controller. The warnings appear in my AppDelegate (code is below), but I included the method from my root controller on how I call this new subview also in case that too has a problem.
the alerts that continue to come up are that the local declaration of navController hides an instance variable.
When I launch the application (which used to open fine) it now simply exits out...
#import "SEM2REDOAppDelegate.h"
#import "SEM2REDOViewController.h"
#implementation SEM2REDOAppDelegate
#synthesize window;
#synthesize navController;
#pragma mark -
#pragma mark Application lifecycle
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self.window makeKeyAndVisible];
SEM2REDOViewController *firstController = [[SEM2REDOViewController alloc]
initWithNibName:#"SEM2REDOViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc]
initWithRootViewController:firstController];
[self setNavContorller:navController];
[window addSubview:[navController view]];
[navController release];
[firstController release];
return YES;
}
then here is the method inside of my first view controller
- (IBAction)chooseFirstMeeting:(id)sender {
SelectRotationController *selectView = [[SelectRotationController alloc]
initWithNibName:#"SelectView" bundle:[NSBundle mainBundle]];
[selectView.navigationItem setTitle:#"Select First Meeting"];
[self.navigationController pushViewController:self.selectRotationController animated:YES];
self.selectRotationController = selectView;
[selectView release];
}
I know this may be an extremely simple question but I've just started this. doing an intensive study on programming in high school as an added course so I'd really appreciate any help!
Rename navController
UINavigationController *navController = [[UINavigationController alloc]
initWithRootViewController:firstController];
into something else. You can do this automatically by control-clicking word "navController", choosing "Refactor" from context menu, and then "Rename...".
Explanation:
The problem, I believe, in your local variable navController having the same name as instance variable under synthesized declared property navController.
Edit:
Also, this seems to be a typo:
[self setNavContorller:navController];
Correct:
[self setNavController:navController];

Load a UIViewController as main controller

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.

Programming iOS: clarifications about Root View Controller

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;
}

Push NavigationController from UIScrollView

how can I push a new view onto the stack of a NavigationController from a UIScrollView?
I tried
[self.navigationController pushViewController:myNewViewController animated:YES];
but get "navigationController not in structure or union".
regards
You don't have a navigation controller in your app. You need to create one. Something like:
In your appDelegate create a UINavigationController instance variable and then use your existing viewController as the rootViewController of the navigation controller.
e.g. in pure code using a UITableViewController (you can use xibs as well which your template app probably does).
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Create root view and navigation controller
UITableViewController *rootViewController = [[[UITableViewController alloc] initWithStyle:UITableViewStyleGrouped] autorelease];
self.navigationController = [[[UINavigationController alloc] initWithRootViewController:rootViewController] autorelease];
// Not necessary if you're using xibs
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Add the nav controller's root view to the window
[window addSubview:navigationController.view];
[window makeKeyAndVisible];
return YES;
}
Then you can push/pop new views in the way you're attempting.