iOS Application launch black screen, UINavigationController, Nib, RootViewController - ios

I've got the following app, whose RootViewController is named TopicsViewController.
When I run it, there aren't any errors or breaks but the screen is black. No table, populated or empty, just a black screen. Not sure which of the following is happening:
Is there something wrong with my application didFinishLaunchingWithOptions method in relation to a parser initlizing in it?
Is it something to do with my nib file for the TopicsViewController?
I can show more code from my TopicsViewController class if needed.
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
///////////////////////////////////////////
***initializing code for parser which populates TopicsViewController (not shown to save space)*****
///////////////////////////////////////////
UIViewController *rootController =
[[TopicsViewController alloc]
initWithNibName:#"TopicsViewController" bundle:nil];
navController = [[UINavigationController alloc]
initWithRootViewController:rootController];
self.window = [[UIWindow alloc]
initWithFrame:[[UIScreen mainScreen] bounds]];
[self.window addSubview:navController.view];
[self.window makeKeyAndVisible];
return YES;
}

Instead of:
[self.window addSubview:navController.view];
Write:
self.window.rootViewController = self.navController;

Related

starting ios project without storyboard

Im having some troubles to start an iOS app using xibs instead of storyboard. The problem is that im getting a black screen and the first view controller is not being called (added break point to viewDidLoad method).
In the app delegate header i have declared this:
#property (strong, nonatomic) UIWindow window;
#property (strong, nonatomic) ViewController *viewController;
And in the didFinishLaunchingWithOptions method i have this implementation:
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
navController.navigationBarHidden = YES;
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
Looking over some forums i found that i should be allocing the window so i added this as the first line of the function
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
The problem is that, when i do this, the app crashes after returning from didFinishLaunchingWithOptions method (SIGABRT without any trace).
I also tried to make the navController a property and also instantiating a default UIViewController class initing the same xib
What am i doing wrong?
Thanks and regards
Hope this helps you:
Delete the view controller and storyboard file and new viewController.h,viewController.h.m ,viewController.xib file.
#import "AppDelegate.h"
#interface AppDelegate ()
#end
#implementation AppDelegate
#synthesize viewCOntrollerobj;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewCOntrollerobj = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:self.viewCOntrollerobj];
//navController.navigationBarHidden = YES;
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
return YES;
}
To change your project to use xibs instead of storyboards start by creating a xib for each view controller. You will need to change the File's Owner to class to the view controller you are creating the xib for. Then link the File's Owner view outlet to the view in the xib.
After that, select your app target and change the Main Interface drop down to be empty. Now you can delete the storyboard file.
Finally, initialize your window in the app delegate's application:didFinishLaunchingWithOptions: method and set your initial view controller as the root view controller of the window. Then call makeKeyAndVisible on your app delegate's window and you should be good to go.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
self.window = [UIWindow new];
self.window.rootViewController = [ViewController new];
[self.window makeKeyAndVisible];
return YES;
}
In xCode 11:
Step1:
-> Delete the storyBoard file
Step2:
Under yourProject > General > deployment info > main interface -> delete reference to storyboard
Step 3:
In info.plist > Application Scene Manifest > Scene Configuration > Application Session Role > item 0 > storyboard name
-> Delete the line
Step 4:
In SceneDelegate.m
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.windowScene = (UIWindowScene *)scene;
self.window.rootViewController = [[UINavigationController alloc]
initWithRootViewController:ViewController.new];
[self.window makeKeyAndVisible];
}
make sure to import your viewController headfile like so: #import "ViewController.h"
OK, at last i got it.
What i had to do is just add again
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
After this, just delete the .h, .m and .xib and create them again.
For any reason its working fine now.
This is a kind of "out of the box" solution, so it is irrelevant to your code. Specially since I don't see anything wrong with your code.
I had the same problem and tried for a long time to fix the code, what worked for me was finding an example project (in github for example) that uses xibs.
Download it and then edit it to make your application it is guaranteed to work. It is a shame that Xcode wants to force us to use their storyboards with these kinds of problems.
I didnt try with XIB, but this thing is working fine here:::
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.viewController = [[ViewController alloc] init];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
navController.navigationBarHidden = YES;
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
// Override point for customization after application launch.
return YES;
}
and in ViewController's viewDidLoad
- (void)viewDidLoad {
[super viewDidLoad];
[self.view setBackgroundColor:[UIColor greenColor]];
// Do any additional setup after loading the view, typically from a nib.
}
And the green color comes on the screen.
Initialize the window before setting the root view controller for the window.
That's the only problem that i see in you code, as the rootViewController is set to a nil window, and after that you are initializing.
Leave main interface empty
Add new ViewController.xib to the project and mark its file's owner class as "ViewController"
In AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
NSArray* xibContents = [[NSBundle mainBundle] loadNibNamed:#"ViewController"
owner:nil
options:nil];
ViewController* vc = [xibContents objectAtIndex:0];
UINavigationController *navigationController =
[[UINavigationController alloc] initWithRootViewController:vc];
self.window.rootViewController = navigationController;
[self.window makeKeyAndVisible];
return YES;
}
build and run
In Swift 3.0
//MARK: Initial View Controller
func initialViewController(){
self.window = UIWindow(frame: UIScreen.main.bounds)
let rootViewController = UIViewController(nibName: "HomeVC", bundle: nil)
let navigation : UINavigationController = UINavigationController(rootViewController: rootViewController)
navigation.isNavigationBarHidden = true
self.window?.rootViewController = navigation
self.window?.makeKeyAndVisible()
}
in appdelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
initialViewController()
return true
}
Xcode 11 with SceneDelegate
In SceneDelegate.m
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.windowScene = (UIWindowScene *)scene;
self.viewController = [[ViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
}
No need to do anything in AppDelegate.m

Instantiating UITableViewController in AppDelegate to work with Storyboard iOS

Need help with a "Application windows are expected to have a root view controller at the end of application launch" warning in my console when running my app. It's a core data test I am working on. I am not getting the NSLog statements I am using for testing, only the previous message.
I created a new project from an Empty Application. My app delegate didFinish method code was generated to look like 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;
}
I added a storyboard and set it as the Main Interface. Then added a UITableView to the storyboard. Created a UITableViewController by adding a file and set it as the UITableView's class in the identity inspector.
It seems to get rid of the warning I should set the rootViewController. How do I set my UITableViewController as the rootViewController if I did not instantiate it in the appDelegate.m file? Alternately, If I do instantiate it in the appDelegate.m like so
UITableViewController *tableViewController = [[UITableViewController alloc]init];
self.window.rootViewController = tableViewController;
how do I associate tableViewController with corresponding .h and .m files?
Using Xcode 5.0.1, deployment target 7.0
When you add a storyboard to your empty application, and set the property "Main Storyboard file base name" in your Info.plist as the name of your storyboard, then the application instantiates your "window" object and assigns an instance of your storyboard's "initialViewController" as the "rootViewController" property of your window object. So you don't see the warning :
"Application windows are expected to have a root view controller at the end of application launch" when you do :
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
return YES;
}
This works fine.
However, in the code :
-(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 were using storyboards, you have overridden default behaviour by creating a new window object, which no longer has the rootViewController provided by storyboard. In this case, you have to explicitly add a root view controller to your window object.
-(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];
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:#"YourStoryboard" bundle:[NSBundle mainBundle]];
YourTableViewController* vc = (YourTableViewController*)[storyboard instantiateInitialViewController];
_window.rootViewController = vc;
[self.window makeKeyAndVisible];
return YES;
}
Hope this helps !!
In StoryBoard set the desired controller as initialViewController.
In AppDelegate.m
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
youRootViewControllerObject = [storyboard instantiateInitialViewController];
This way you can access YouRootViewController class.
I did a lot of research and finally found out the right way to do this
in appDelegate.m instead of
- (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;
}
The code should simply be
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
return YES;
}
See Sitepoint's helpful page for more detailed information
http://www.sitepoint.com/ios-application-development-storyboards/

Can [self.window makeKeyAndVisible]; be called before setting rootviewcontroller

My requirement is that UITabBarController is the rootviewcontroller and on very first time of app launch I want to show login procedure which is inside UINavCon, and I am displaying it through presentViewController.
I dont want the UITabBarController visible for first time and dont want to how login UINavCon popping as modal.
I want to make user experience that if app starts for first time login UINavCon should be visible. So here is my code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.window makeKeyAndVisible];//is it correct to call it here?
LoginVC *loginObj = [[LoginVC alloc]init];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:cellPhoneNumber];
self.tabBarController = [[UITabBarController alloc]init];
self.window.rootViewController = self.tabBarController;
[self.tabBarController presentViewController:self.navigationController animated:NO completion:^{}];
return YES;
}
I am calling [self.window makeKeyAndVisible]; on second line right after uiwindow alloc init. Is it correct do this or I can experience problems like viewcontroller not receiving events or orientations notifications?
you can call it whenever you want. Calling it affects the window's z-index and screen property.
it doesnt depend on any specific content being set.
You haven't mentioned that whether you got the code working or not by using your implementation. Anyways I have done similar kind of implementation recently where we need to present login controller and then tabBarController after logging in, so just sharing my implementation.
Create your login controller and present it in didFinishLaunching method.
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
LoginController *loginCObj= [[[MainScreenController alloc]init]autorelease];
UINavigationController *navigationControllerObj = [[[UINavigationController alloc]initWithRootViewController:loginObj]autorelease];
self.window.rootViewController = navigationControllerObj;
[self.window makeKeyAndVisible];
After that on succesful login in your login view controller, call an appDelegate public method
In login controller
AppDelegate *appDel = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[appDel applicationLoggedInSuccesfully];
In your appDelegate file, add a method like this:
-(void)applicationLoggedInSuccesfully{
UINavigationController *nv1 = [[[UINavigationController alloc] initWithNibName:nil bundle:nil]autorelease];
TabController1 *v1 = [[[TabController1 alloc] initWithNibName:nil bundle:nil]autorelease];
[nv1 pushViewController:v1 animated:NO];
UITabBarController *tabController = [[[UITabBarController alloc] init]autorelease];
tabController.viewControllers = #[nv1];
tabController.delegate = self;
self.window.rootViewController = tabController;
[self.window makeKeyAndVisible];
}
Hope it will help you.

How to load different view controllers based if URL is provided on start in iOS

I have an app, it authenticates with Instagram using safari, and when it returns I want it to load table view right away, without the login view.
Here is what I do now:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
DVGViewController *myVC = [[DVGViewController alloc] initWithNibName:#"DVGViewController" bundle:nil];
self.viewController = [[UINavigationController alloc] initWithRootViewController:myVC];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
// some code skipped
UITableViewController *myTVC = [[DVGTableViewController alloc] init];
self.viewController = [[UINavigationController alloc] initWithRootViewController:myTVC];
return YES;
}
At the moment I still get first method to work every time, although second method is triggered too, since I get calculations from url with it and I know that. Why it doesn't load tableView I don't know.
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
method will call if you app is come fro m specific URl like from facebook auth or from safari then this method will call
I have found an error. In second method I have never set window and rootViewController. Adding this code to second method helped.
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];

Basic table program in iOS - How can I tell my table to reload data from the application delegate?

I've got your standard table application built right now. Window has a UINavigationController as its rootViewController, and that UINavigationController was initialized with its rootViewController as my custom UITableController.
My applications table data changes over time. If I open my application up from a suspended state then my data is stale. How do I get applicationWillEnterForeground to update my data? I tried something awkward like
- (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];
HabitsTable* vc = [[HabitsTable alloc] init];
[vc initCoreData];
UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:vc];
self.window.rootViewController = nav;
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
[[[[self window] rootViewController] navigationController] rootViewController]
}
But, no surprise, that doesn't work. I'm not sure how to get at my UITableController?
I'd recommend using the NSNotificationCenter. You can see a nice example of how to use the class here.
I believe your close try:
UINavigationController *navController = (UINavigationController*)[[self window] rootViewController];
HabitsTable *tableView = (HabitsTable*)[navController topViewController];

Resources