"Application windows are expected..." warning, but app runs fine - ios

I'm getting the following error in my console upon launching my iPad-based iOS app:
"Application windows are expected to have a root view controller at the end of application launch"
I've looked at answers to other questions that reference this error, but none of them seem to be my particular issue.
In fact, the only symptom I have that there is a problem at all is the message in the console at app launch. My app seems to run fine and performs exactly as I desire.
I'm using a single storyboard file (Main.storyboard) to generate my app's UI (with a couple of XIB files for custom views). All of my UIViewController subclass UI is contained in the single storyboard. This storyboard is specified as the 'Main Interface' in my 'Deployment Info'.
Here is the code in my AppDelegate (I've removed some non-UI-based app initialization code):
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
MSSAppSingleton *app = [MSSAppSingleton singleton];
// Other, non-UI code, like TestFlight, etc.
UISplitViewController *split = (UISplitViewController *)self.window.rootViewController;
UINavigationController *leftNavVc = split.viewControllers[0];
UINavigationController *rightNavVc = split.viewControllers[1];
app.containerSplitViewController = split;
app.leftRoot = leftNavVc.viewControllers[0];
app.rightRoot = rightNavVc.viewControllers[0];
return YES;
}
This code appears to run without a problem. I'm grabbing these references for later UI manipulation, and all of that is working as desired. Every single one of the lines of code above runs as I would expect. self.window has a valid reference. self.window.rootViewController does, too.
So, this isn't really a "problem", except I follow the philosophy of "treat every warning as an error" and would love to get this warning to disappear. Has anyone else seen this? I'm using Xcode 5.0.2 and running the iPad 7.0.3 simulator.

MSSAppSingleton *app = [MSSAppSingleton singleton];
is supposed to be called before
app.containerSplitViewController = split;

Xcode likes it when you set the root view controller
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.window setRootViewController: someViewController];
[self.window makeKeyAndVisible];
I don't use storyboards myself though.
You may need to set the root instead of just getting it and then applying things to it to make it happy.

Related

"Application windows are expected to have a root view controller" message when adding view immediately after launch, iOS 9 only

My app sends a request at startup and displays a brief message to users when it succeeds, by means of MTStatusBarOverlay. Unfortunately, my current implementation seems to run afoul of iOS 9's view life cycle paradigms. I get the message
Application windows are expected to have a root view controller at the end of application launch
and the app crashes. The app works fine on iOS 7 & 8.
From searching around online, it seems like this might occur when trying to add the message view to the view hierarchy before the root view controller is established for the app's UIWindow, but that doesn't seem to be the case here, see below.
Here is an excerpt of the UIApplicationDelegate implementation:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[...]
self.window.rootViewController = [[MyViewController alloc] init];
[...]
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[MyDataManager sendRequestWithCompletion:^{
// Displays a message with MTStatusBarOverlay
[self showSuccessOverlay];
}];
}
application:didFinishLaunchingWithOptions: is called before applicationDidBecomeActive: so it seems like there should never be an issue with rootViewController being established.
Why is this happening? What's different about iOS 9 that's causing the app to break?
MTStatusBarOverlay is a subclass of UIWindow, so instantiating one during app launch adds that UIWindow to the list that iOS checks for a populated rootViewController when launch completes.
I was able to work around the issue by instantiating and assigning a dummy controller before using the overlay, like so:
[MTStatusBarOverlay sharedInstance].rootViewController = [UIViewController new];
[[MTStatusBarOverlay sharedInstance] postMessage:#"Message"];

iOS app crashing after setting UIWindow rootViewController in iOS 9

My app was working great until running it on iOS 9.
In the AppDelegate, I check whether the user is logged in or not. If they're not logged in, I send them to the login screen with the following line:
self.window.rootViewController = [self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:#"Login"];
After the user logs in, I attempt to send them to the main app with the following line:
self.window.rootViewController = [self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:#"Tabs"];
This worked in iOS 8, but now it crashes the app. And it's a bad crash. The whole device has to reboot (although it's a very quick one, so I think it's more like a SpringBoard reboot or something).
I'm seriously at a loss as to why the first line works and the second doesn't. Any help is much appreciated!
EDIT
I ended up recreating the entire UIViewController flow that was crashing and it works fine now. As far as I can tell it was some strange bug in the new Xcode. Not considering this an answer, so if anyone has a true answer then feel free to share it.
Not sure why, but this works for me in iOS9. It might be that you're trying to do this already in the AppDelegate before the window has been properly loaded?
I've got a first ViewController in the storyboard and does this redirecting there instead.
UIViewController *viewController = [[UIStoryboard storyboardWithName:#"Storyboard"
bundle: nil] instantiateViewControllerWithIdentifier:#"viewController"];
[[[[UIApplication sharedApplication] delegate] window] setRootViewController:viewController];
The code to set the root view controller works in iOS9 without issues.
[[[[UIApplication sharedApplication] delegate] window] setRootViewController:viewController];
If you get a crash in that line, it surely means that the viewController initialization logic or any of its subviews are throwing at some point.
Problem is that working in the simulator the app will crash with no errors in the output. Best thing to do here is setting a breakpoint in the viewController logic (ie: viewDidLoad) and check what line is causing the error.

Getting top UIWIndow/UIView on device using public/non-public/private API

I'm trying to find out how to find the top most view using non-public/private api, is there any way doing it (iOS 7.1.2)?
Edit:
Maybe I wasn't clear,
I want to get the top most view no matter what app is active now (facebook, whatsapp, games, lockscreen, calendar, etc.).
Options
If I understand correctly, you're wanting to show a UIView on top of another application's window. In the app sandbox, you are only allowed access to your own application's window. Jailbreaking, however, will allow you to do this, but it's not exactly simple.
In order to show a view on top of applications, you have three choices. Which option you choose depends on what you're trying to do.
Inject your code into third-party applications
Inject your code into SpringBoard
Use a combination of methods 1 and 2.
Option 1
If you choose to go with this route, your code will be running inside each third-party application. This allows you to modify the view hierarchy of the application to show your own window or even modify existing ones. Since you're code is running in the application, you can obtain the key window by simply calling:
[[UIApplication sharedApplication] keyWindow]
Option 2
If you choose this option, your code will be running regardless of what application is open. By obtaining the main window, you can show UI over anything, including system alerts. I've posted an example of this to GitHub at rpendleton/tutorials/so-26032688. The example shows an alert anytime the user takes their phone out of silent. The code to retrieve SpringBoard's window is:
[[NSClassFromString(#"SBUIController") sharedInstance] window]
Option 3
The third option, and the one you'll likely end up using, is a combination of both options 1 and 2. In this scenario, you'll inject your code into third-party applications, and then communicate with SpringBoard to decide what needs to be done. Typically, your application would communicate with SpringBoard, then SpringBoard can relay that information to the desired application. You may be able to communicate directly between your application and a third party application, but I haven't tried that.
Communication
In order to communicate between your application and SpringBoard / other third-party applications, you'll need to use a messaging system. An easy way to do this communication is via a open source library called RocketBootstrap.
Screenshots
The screenshot on the left is from the example I posted on GitHub, and the screenshot on the right is from one of my tweaks AppScan. Although I'm presenting an alert in both, you can show whatever view you desire.
try getting window of AppDelegate like this
UIWindow *window = ((AppDelegate*)[UIApplication sharedApplication].delegate).window;
And then access window's last object like this
[[window subviews] objectAtIndex:0];
or like this
[[window subviews]lastObject];
If you want to addsubview to it
[[[window subviews] objectAtIndex:0] addSubview:view];
Reading the question and the comments this is what you're looking for...I think, not the most detailed question I saw:
UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
window.rootViewController = self;
window.windowLevel = [[UIApplication sharedApplication] keyWindow].windowLevel + 1;
[window makeKeyAndVisible];
You want to use this as part of the view controller that you want on top.
You question is not totally clear, can you explain why you need to do that?
By the way most probably what you need is the key window first, as stated in the doc:
The key window is the one that is designated to receive keyboard and
other non-touch related events. Only one window at a time may be the
key window.
What you can do is ask for the application current key window:
NSArray * array = [[UIApplication sharedApplication] windows];
Iterate over that array to find the key window and then check for its subviews:
UIView * topView = [[window subviews]lastObject]
If you are looking to a way for emulate an alert view, You should create your own UIWindow and later ad your view controller that handles the "alert" as a rootViewController and make it" key and visible".
Something like that :
UIWindow *alertWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
alertWindow.rootViewController = [[AlertViewController alloc] initWithXibNamed:#"AlertXib"];
alertWindow.windowLevel = UIWindowLevelAlert;
[alertWindow makeKeyAndVisible];
And when you want to dismiss just set the rootViewController to nil and make the window hidden.
Using the root view controller approach helps into avoid messing with rotation corrections. Even if in iOS8 the rotates.
I've found a good reference here.

How to call a view controller from AppDelegate in iOS

I am creating an iOS app in which I have the following requeriment: the app should show the login screen when it starts the first time and also that screen must also be shown when the app comes from the background to the foreground, in case it has been sent to background during run time.
I have handled to show the screen in both cases. However, when I do it and the app comes from the background, and I click the texfield to type my password, the app gets frozen, and it fails in a thread that I don't know what it means.
I call the screen to be shown when the app comes from background like this, in the applicationWillEnterForeground, in AppDelegate:
self.window=[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
RoomRootViewController* room = [[RoomRootViewController alloc] init];
[[self window] setRootViewController:room];
[self.window makeKeyAndVisible];
Is this the correct way to do so?
Thanks a lot in advance ! I am completely lost with this as I am very new in iOS, so any help will be very appreciated.
Attached in an image you can see where the app fails.
The code you are currently using is completely deleting the root view controller of your app window, in other words, you are deleting all the views and view controllers in your app. If you are not using ARC, this is just one huge memory leak. If you are, it's still not a very good idea.
In your applicationWillEnterForeground: method, try using this code instead:
RoomRootViewController* room = [[RoomRootViewController alloc] init];
[self.window.rootViewController presentViewController:room
animated:NO
completion:nil];
This will display the RoomRootViewController over the top of all your app's current views, instead of deleting them. You can then dismiss it like this:
[self.window.rootViewController dismissViewControllerAnimated:YES
completion:nil];
and easily return to the rest of your app.
It will be very messy if you are using this line of code
self.window=[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
It means every time you are creating new instance of UIWindow which will contain UIViewController and all other component each time. Which means when you go to background and comes to foreground the old window instance has been flushed off and it will contain new components that's why when you click on the UITextField it has been deallocated, The reason you are getting error. Don't create new instance of window and use the code as #PartiallyFinite does.
Hope this helps.

Where does the simulator save files (Xcode not updating files)?

I am having some trouble with Xcode not updating files that I have updated (e.g. database, jpgs etc), even though I have carefully deleted the old files and removed the references. This problem consists since Xcode > 4.2.
Is there a place (maybe hidden files) where the simulator drops data except the derived data folder and
~/Library/Application Support/iPhone Simulator/[OS version]/Applications/[appGUID]/
Many thanks in advance
PS: yes, I usually clean project, delete derived data, delete all simulator files in the abov directory, delete the project and restart the mac. And still there seems to be a reference to the old data (like jpg, database etc), even if I can't find it on the file system...
Goto Product>>Clean Build Folder. Or alternatively, Reset Simulator from iOS Simulator menu. That way your app will be rendered new in the simulator and used after a complete refresh and link-up with your project files.
Uninstall the app in the simulator. That way you get rid of everything.
Some times you have conflicting code in didFinishLaunchingWithOptions that you forgot to remove. Make sure that function only has the statements you want.
For example, the code below is setting the background to white. No matter what you add to the storyboard you will still see all white.
- (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;
}
Change it to:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
return YES;
}
Uninstall the app in the simulator and then goto Product>>Clean. This works for me.

Resources