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];
}
I have a workspace with MFSideMenu. One voice of this menu has 3 UIViewController I would scroll with UIpageControl. it's possible?
How can it work?
Thanks
Basic example:
In your app delegate
#import "MFSideMenu.h"
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Do other stuff
MFSideMenuContainerViewController *container = [MFSideMenuContainerViewController
containerWithCenterViewController:centerViewController
leftMenuViewController:leftMenuViewController
rightMenuViewController:rightMenuViewController];
self.window.rootViewController = container;
[self.window makeKeyAndVisible];
}
For more information:
https://github.com/mikefrederick/MFSideMenu
I made an empty application, then later I and added a UITabBarController in the Storyboard. Then I checked it as the initial viewcontroller and connected two NavigationControllers to represent the tabs.
But if I run the app now it says that "Application windows are expected to have a root viewcontroller at the end of application launch." and shows a white screen.
My AppDelegate looks like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
I have to add the TabBarController as the main window, but how to do this?
If TabBarController was made programmatically I would have figured it but how to when it's created in storyboard? Can I make a property for it in AppDelegate? How to hook it in storyboard in that case?
You can hook storyboard inside your target settings Then make sure that your UITabBarController inside of your storyboard is initial UIViewController . You can also use this code:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *initialViewController = (UIViewController *)[storyboard instantiateViewControllerWithIdentifier:#"IdentifierOfYourViewController"];
self.window.rootViewController = initialViewController;
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;
}
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.