UIWindow not filling screen for new devices? - ios

I'm working with an old Xcode project which is roughly 7/8 years old and I've migrated it to Objective-C 2.0 and to support ARC. The project didn't support Auto-Layout (this was just before it was released) prior to me working on it. I've managed to clear up a lot of the errors/issues i was having with running it in a more modern Xcode IDE (10.2.1). For testing purposes I have implemented this code into the AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, UIScreen.mainScreen.bounds.size.width, UIScreen.mainScreen.bounds.size.height)];
[self.window setBackgroundColor:[UIColor redColor]];
self.window.rootViewController = [UIViewController new];
[self.window makeKeyAndVisible];
return YES;
}
which gives me this for some reason:
This is the result when i run on a iPhone X, iPhone XR or iPhone XS Max, it looks like the top and bottom margins (safe areas) of the screen are not being picked up on. When i debug the view hierarchy they aren't being picked up on either, it just shows the red space? When i throw this code in a new project it works fine and fills up all the space. I'm wondering that because this is a old project there might be a build setting which is restricting the UIWindow from expanding to allow support for new devices?
Also as a side note I've made sure the UIWindow object isn't being manipulated elsewhere.

Try to add "Launch screen interface file base name" (UILaunchStoryboardName) to your Info.plist
It seems that the presence of this key tells the system that you natively support new device types and size classes, so your window can fill all available area.

Don't mess with the storyboard.
Add UILaunchScreen dictionary entry to your .plist.
Include UIColorName string value with background color name defined in the Assets.xcassets.
<key>UILaunchScreen</key>
<dict>
<key>UIColorName</key>
<string>launchScreenBackground</string>
</dict>

Related

ViewController offset after device rotation in iOS8

I am experiencing an odd problem with legacy code running in iOS8. The code was originally written pre-iOS6, pre-storyboards (using nibs) and functioned without issue on iOS7. However, strange behavior began to occur when running on iOS8.
The app is set to run only in landscape (left or right). Therefore it should support autoRotation from landscape-left to landscape-right. The first problem was that the initial view controller was loaded in portrait and one side was cut off. This issue was addressed with the following code in the AppDelegate:
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
[self.window setFrame:[[UIScreen mainScreen] bounds]];
Changing the order of these calls allowed the view controller to load in its proper orientation and did not affect apps running in iOS7. However, now when the device is rotated 180 degrees I get the following results. See images...
Here is the app at initial load:
And after a 180 degree rotation, I get this offset effect:
Any ideas on how to address this issue? Again, everything is fine in iOS7 or previous. THanks!
I had a problem just like yours when iOS 8 first appeared, and it had nothing to do with the opening window-creation incantation! It has to do with your Info.plist. It is crucial that the first orientation listed in the Info.plist be an orientation that the root view controller actually permits.
So, let's say your root view controller permits only landscape. Then you will get the problem you describe if your Info.plist looks like this:
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
See the bug? Portrait comes first. No. If the root view controller permits only landscape, then one of the landscape orientations must come first.
[You can actually see me experiencing the issue, then discovering and reporting the solution, here: https://stackoverflow.com/a/24467576/341994]
Also, I have to wonder whether you might be doing anything else that upsets the rotation system. Note that the nature of rotation itself, including the coordinate system, what rotates, when it rotates, etc., has completely changed in iOS 8; this is probably the biggest single change in iOS 8. So if you have old code that makes under-the-hood assumptions about what rotation is (e.g. that it involves a transform), that code will now break. You do not show any of that in your question so I can't provide specifics about what you might be doing.
Finally, just for the record, the correct minimal opening incantation is (this is Swift code but I'm sure you can translate):
func application(application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
self.window!.rootViewController = UIViewController() // or whatever it is
self.window!.backgroundColor = UIColor.whiteColor()
self.window!.makeKeyAndVisible()
return true
}
You should use some autolayout constraints on the view controller so that it sticks to the left / upper and bottom of the parent container.
Here are a few ideas:
1) Initialize your window with a frame, don't set it afterwards
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
2) Make sure the autoresizingMask of your rootViewController's view is FlexibleWidth+FlexibleHeight and you don't have flexible margins anywhere in there.
3) Make sure your App's target explicitly has only the orientations you want in the General->Deployment Info section. It sounds like you have it only going into the orientations you want, but just check that to make sure!
I wasted a whole day with a similar problem while migrating our App from iOS 7.x to iOS 8.4. The views had mystic offset an wrong size after device rotation.
Our App uses a UITabBarController as RootViewController and the number of Tabs can change dynamically. On the iPad all views support all orientations. On the iPhone, only one view can be rotated, all other are firmly set to portrait. Because the number of views can change dynamically, I have a property that
stores the possible orientations for each view. I return the content of the property every time UIViewController.supportedInterfaceOrientations() was called from iOS.
While debugging the problem I noticed that the function UIViewController.supportedInterfaceOrientations() was called immediately after AppDelegate called the function UIWindow.MakeKeyAndVisible(). At this time, my code had no chance to initialize the property, so UIViewController.suppoertedInterfaceOrientations() returned 0 to iOS. After i changed the code so that my property is initialized before UIWindow.MakeKeyAndVisible() was called, the mystic
size and offset problem was gone!!!
My conclusion: Don't mess the iOS with a wrong or missing UIViewController.supportedInterfaceOrientations() function ;-)

Xcode 5 Simulator Blank White Screen

I just installed Xcode 5 (or the latest version) and created a new project. I created a storyboard, and added a label, but when I open my application in the iPhone simulator, I simply get a blank white screen with a status bar. What am I doing wrong?
I have OS X 10.9.1 Mavericks.
I know I'm quite late to this, but the solution to this problem is quite simple and is even shown in one of Apple's own tutorials.
Assuming that you started off with an "Empty Project", created a storyboard from scratch, and set your storyboard as the main interface, you need to remove a few lines in the first method of AppDelegate.m.
This:
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;
Should become just this:
return YES;
I'm going to assume that you started an empty project, which doesn't start with a storyboard and then after creating the project, you created a storyboard file.
You have to tell your app which storyboard to load.
In the below screen shot, you'll want to click the "Main Interface" drop down and select the storyboard you want to start your app with.
This is the "Deployment Info" section of the "General" tab of your targets.
You also need to add a couple lines of code to your AppDelegate.m. It should 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.
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"YOUR_STORYBOARD_NAME" bundle:[NSBundle mainBundle]];
UIViewController *vc =[storyboard instantiateInitialViewController];
self.window.rootViewController = vc;
[self.window makeKeyAndVisible];
return YES;
}
Your project does not have a view controller. When you created your project, you should have started with a "Single view project", which would have created a view controller for you. In that case, you would have been able to see your label.
EDIT TO FIX:
If you would like to fix this, remove the property "Main nib file base name." This can be found in the "info" tab of your target.
The problem:
It seems that when you created your application, you selected the "Empty Application" template. Then you added the Storyboard from the user interface section. When you added the label and ran the application, you can't see the "Hello, World" label, because the application does not have a root view controller at the end of the application launch.
Try to create a "Single View Application".
Just wanted to chime in on this thread and shed some light on the matter. I myself was working on my first project and was getting the white screen. I found this article and it helped and it didn't, but this is what worked for me. Everyone is right on what they posted, but I was running 9.2 simulator when in fact I only have 9.1 installed (if you need help with this go to Xcode> Preferences>Downloads and download the appropriate package. Once I did that I ran the simulator and got the white screen. Now my white screen had the carrier and batt icon at the top. To fix this issue in Simulator: Hardware>Device>9.1 and a reboot occurred and then it works...
Hope this helped.
SithAdmin
I had the same issue (blank screen) for a stupid simple error. Actually, the elements appeared and soon fade away.
My mistake was that I was not creating in in Main.storyboard (but LaunchScreen.storyboard in place, so that it obviously disappeared couple of seconds after start).
Stupid but at least, quick to check: create views in Main, not LaunchScreen...
Click "Main.storyboard" -> on right prat "Interface Builder Document" uncheck "Use Auto Layout, "Use Size Classes" & "Use as Lunch Screen"

iOS PhoneGap app upgraded to Cordova 2.1 - content ignores status bar entirely

I just finished upgrading an iOS PhoneGap app to Cordova 2.1. The app builds fine, but when running it on the simulator, the content of the app seems to completely ignore the fact that the status bar is there. 20px of content is hidden underneath the status bar now and I cannot seem to add padding to shift it down even.
How do I fix this?
If you upgraded your application to use PhoneGap 2.1 from another version, your MainViewController.m file may not be up to date.
You need to have the following code in it:
#pragma mark - View lifecycle
- (void)viewWillAppear:(BOOL)animated
{
// Set the main view to utilize the entire application frame space of the device.
// Change this to suit your view's UI footprint needs in your application.
self.view.frame = [[UIScreen mainScreen] applicationFrame];
[super viewWillAppear:animated];
}
Once you have this function, your App will be back to normal!
(Solution found here)
I am assuming you want the status bar to apear.
Check to make sure the code does not have this line:
[[UIApplication sharedApplication] setStatusBarHidden:YES animated:NO]
Also, you may have set it to be hidden in interface builder.
Another place is in the info.plist for your app, check for this line
<key>UIStatusBarHidden</key>

UIImageView in appDelegate displayed in simulator, but not on device

I've got a weird problem: I want to have a icon in one of my apps that stays above every other Controller/View. My idea was to create a UIImageView in the main XIB-File (the project started pre-iOS-5) above the UITabBarController that handles the Content Views.
I added the ImageView in the didFinishLaunchingWithOptions of the appDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
// Add the icon view that shows current working status (working/pause)
[self.window addSubview:self.statusIcon];
...
}
Initially the ImageView is hidden, it will only be shown when a button is pressed. Then i will assign the UIImage and unhide it:
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[delegate.statusIcon setImage:statusIconWorking];
[delegate.statusIcon setHidden:NO];
This works in the simulator, but not on a device (tested it on iPod touch 4. generation and iPad 3. generation (retina)).
Could someone please tell my it doesn't work that way? It's not a image problem (it exists on the device, and i tried to load other Image in the ImageView that are displayed correctly in other parts of the app).
Thank you.
I observed the same problem once and did not find a solution here. Some hints were helpful though, so I finally nailed it down. It happened only once and I noticed it some days after an xcode version change. However, I never found out what the solution was and if that was really caused somehow by the version migration.
The reason was that the image file was not part of the bundle. Check your boundle settings. Do so for every target that you may have.
My observation was: The image file was included in the bundle on the simulator. It did not only remain there from one version to the next. It was re-installed even when I removed the app from the simulator. I did so either removing it using the simulator's gui as if removing from a real device and I manually removed it from the simulator's file system - just to be sure. In any case the file was re-installed.
On the device it was different. Create an IPA or APP bundle as if you would do for beta testers of for submitting to the store. Have a look into it. (Changing the file name to .zip and unzipping may help to look into the bundle.) I bet that you will not find your image there.
Solution: doublecheck your project settings and ensure that all resources are properly included for all targets respectively.

Xcode 4.2 iOS Empty Application and storyboards

I'm an Xcode newbie, and I'm trying to make my first training app. Since apparently Empty Application template is the only template that offers pre-integrated Core Data, I choose that. However, after that, I can't get UI to work (it remains empty).
What I did:
Empty Application template
New iPad Storyboard file
Splashed Tab Bar Controller onto it
Changed Main Storyboard in Project's Summary view
Hit ⌘R
Stared at pure-white iPad screen, without any tabs
I tried diffing against another project that I created as a Tab Bar Application (which does reflect my Storyboard changes), without any insight.
Comment out (or remove) the window creation and display code in AppDelegate.m as follows:
- (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;
}
When using a storyboard, a main UIWindow is created for you automatically. What is happening in your case is that you are creating another white window and putting it over the top of the tab UI.
ALSO - note that the Master/Detail template also gives you a core data option.
For an Empty Application project, you have to do two things, after you've added your Storyboard file...
Add a row to your project Info.plist file:
Key: Main storyboard file base name
Value: Storyboard
(or whatever you named your storyboard file)
Delete the contents of application:didFinishLaunchingWithOptions: except return YES;:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
return YES;
}
The Master-Detail and Utility project templates also offer Core Data as an option.
The Apple templates for Core Data are pretty horrible. They stuff far too much functionality into the app delegate and they use lazy loading unnecessarily, which just complicates things even further.
You're better off looking at the generated code and adding the functionality as a separate class in a project you start without Core Data.
To answer your immediate question though, the default empty template creates a window programmatically in the app delegate's application:didFinishLaunchingWithOptions: method. The story board sets a window up itself, so you need to remove that code from the app delegate. The only thing you need in that method is return YES;.

Resources