UIScreen bounds smaller than expected on external screen - ios

I want to place content on an external screen (for now a MacBook Pro using Air Server) in full screen, with a screen on a tablet.
I am using an example from https://github.com/quellish/AirPlayStoryboards - which is great. However, I am finding that neither screen is displaying the full screen because the UIScreen's bounds are coming back too small -- the iPad displays a little smaller (letterboxed) and the iPad screen only displays 1/4 of the screen in the top left (origin)
Any idea why this is? The code:
- (void) application:(UIApplication *)__unused application didConnectScreen:(UIScreen *) screen
{
UIStoryboard *storyboard = nil;
UIWindow *screenWindow = nil;
UIViewController *tvViewController = nil;
// Set up external screen
UIScreen *secondaryScreen = [UIScreen screens][1];
UIScreen *primaryScreen = [UIScreen screens][0];
NSLog(#"Screen 1 (iPad): %#", primaryScreen); //print the bounds of the iPad
NSLog(#"Screen 2 (MacBook): %#:", secondaryScreen); //print the bounds and size of the MacBook
UIScreenMode *screenMode = [[secondaryScreen availableModes] lastObject];
CGRect bounds = secondaryScreen.bounds;
// Create new outputWindow
screenWindow = [[UIWindow alloc] initWithFrame:bounds];
screenWindow.screen = secondaryScreen;
screenWindow.screen.currentMode = screenMode;
[screenWindow makeKeyAndVisible];
[screenWindow setScreen:screen];
storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle bundleForClass:[self class]]];
tvViewController = [storyboard instantiateViewControllerWithIdentifier:#"TVViewController"];
[screenWindow setClipsToBounds:YES];
[screenWindow setRootViewController:tvViewController];
[screenWindow setHidden:NO];
// // If you do not retain the window, it will go away and you will see nothing.
[[self windows] addObject:screenWindow];
}
The Log statements return as follows:
Screen 1 (iPad): <UIScreen: 0x1567def0; bounds = {{0, 0}, {480, 320}}; mode = <UIScreenMode: 0x1567dd60; size = 1024.000000 x 768.000000>>
Screen 2 (MacBook): <UIScreen: 0x15680280; bounds = {{0, 0}, {640, 400}}; mode = <UIScreenMode: 0x156804a0; size = 1280.000000 x 800.000000>>:
Does anyone know how I may fix this issue?

You can get the screen size like this:
UIScreen *secondaryScreen = [UIScreen screens][1];
UIScreenMode *secondaryScreenMode = [[secondaryScreen availableModes] objectAtIndex: 0];
CGSize sizeSecendaryScreen = secondaryScreenMode.size;
screenWindow = [[UIWindow alloc] initWithFrame:CGRectMake(0,0, sizeSecendaryScreen.width, sizeSecendaryScreen.height)];
Ref: Setting UIScreen's mode / resolution

I figured this out. It was to do with [UIScreen mainScreen].bounds.size becoming orientation-dependent in iOS8. I got the clue from this post:
Is [UIScreen mainScreen].bounds.size becoming orientation-dependent in iOS8?

In my case there was no launch image for perticular resolution for which I want to support.
For example : If you want to support iPhone5 we need to add launch image of the size of iPhone5.
Please check in your Xcode whether you have all required launch images or not.
This may be your solution. In my case it worked for me!

Related

Resize MoPub iOS banner ad?

I need to have my banner ads stratched/filled all across the width of the screen at the bottom.
My code is working for the devices with the width equal to either MOPUB_BANNER_SIZE.width or MOPUB_LEADERBOARD_SIZE.width
But on other devices (iPhone 5/6/etc and some iPads) my only option is to center the banner. here is the code:
if(!_mopubBanner){
NSString* bannerID;
const CGSize* bannerSize;
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone){
bannerID = #"MopubBannerId";
bannerSize = &MOPUB_BANNER_SIZE;
}
else{
bannerID = #"MopubLeaderboardId";
bannerSize = &MOPUB_LEADERBOARD_SIZE;
}
_mopubBanner = [[MPAdView alloc] initWithAdUnitId:bannerID size:*bannerSize];
_mopubBanner.delegate = self;
CGRect BannerFrameRect;
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
BannerFrameRect = CGRectMake(([[UIScreen mainScreen] bounds].size.width - MOPUB_BANNER_SIZE.width) / 2,
[[UIScreen mainScreen] bounds].size.height - MOPUB_BANNER_SIZE.height,
MOPUB_BANNER_SIZE.width,
MOPUB_BANNER_SIZE.height);
}
else
{
BannerFrameRect = CGRectMake(([[UIScreen mainScreen] bounds].size.width - MOPUB_LEADERBOARD_SIZE.width) / 2,
[[UIScreen mainScreen] bounds].size.height - MOPUB_LEADERBOARD_SIZE.height,
MOPUB_LEADERBOARD_SIZE.width,
MOPUB_LEADERBOARD_SIZE.height);
}
_mopubBanner.frame = BannerFrameRect;
}
I have tried setting custom sizes for BannerFrameRect but the banner ad just keeps adjusting itself to the top left corner of the new frame. It does not get scaled.
is there any way to resize the ad?
thank you
please take a look at the MoPub's sample code here:
https://github.com/mopub/mopub-ios-sdk/blob/master/MoPubSampleApp/Controllers/MPLeaderboardBannerAdDetailViewController.m
You can use autoresizing in the UIView, and in your case you could simply add the following to your code:
_mopubBanner.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin;
hope this helps!
You have two viable solutions:
Use autoresizing masks
_mopubBanner.translatesAutoresizingMaskIntoConstraints = YES;
_mopubBanner.autoresizingMask = UIViewAutoresizingFlexibleWidth;
You'll probably need to set height manually as you only want 'horizontal' stretch.
Much better IMO - use Autolayouts. For this I'd recommend PureLayout as it's really clear and useful.
_mopubBanner.translatesAutoresizingMaskIntoConstraints = NO;
[_mopubBanner autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsZero excludingEdge:ALEdgeTop];

Custom UIWindow on iOS 8.3 iPad works on simulator but not device

We have UIWindow code that has worked for years to put up a "blocker" screen. We noticed recently that on an iOS 8.3 iPad the blocker is offset 256 pixels when the blocker is displayed in the landscape orientation. There are few oddities:
1) This does not happen on the simulator, only the device
2) If the blocker is shown in portrait it is fine
3) If the blocker is shown in portrait and then rotated to landscape it is fine.
4) The gap is 256 pixels, which is the difference between the width and the height, i.e., 1024 - 768 = 256.
We've recently updated to Xcode 6, so this could be a factor as well...
This problem can be easily replicated by using the default Xcode Master Detail project and making a few minor changes to the "insertNewObject" method as shown here:
UIWindow *blocker;
- (void)insertNewObject:(id)sender {
blocker = [[UIWindow alloc] init];
[blocker setBackgroundColor:[UIColor colorWithRed:.0 green:.0 blue:.0 alpha:.8]];
[blocker makeKeyAndVisible];
CGRect r = CGRectMake(0, 0, 768, 1024);
[blocker setFrame:r];
}
If you run this code on the simulator, and tap the "+" button you get:
which is what we expect.
However, this same exact code, running on our 8.3 iPad device gives us:
Any ideas of why the simulator works and the device doesn't? Suggestions? Other things to try?
[UPDATE] We've only found one device where is this a problem, an iPad 2. We've also discovered that setting the rootViewController on the UIWindow "solves" the problem.
Here is the fix we used:
blocker = [[UIWindow alloc] init];
[blocker setBackgroundColor:[UIColor colorWithRed:.0 green:.0 blue:.0 alpha:.8]];
UIViewController *blockerRoot = [UIViewController new];
blocker.rootViewController = blockerRoot;
CGRect r = [[UIScreen mainScreen] bounds];
[blocker setFrame:r];
[blocker makeKeyAndVisible];
We also were able to remove rotation adjustment code since now the view controller managed it properly for us (at least for iOS 8 and later). Here's the code we now use for that: (called when the screen is rotated)
- (void)adjustForRotation
{
if ([UIUtil iOS8OrLater]){
// iOS 8 handles this correctly, no need for adjustments...
return;
}
UIInterfaceOrientation io = [[UIApplication sharedApplication] statusBarOrientation];
if (UIInterfaceOrientationIsLandscape(io)){
CGRect r = [[UIScreen mainScreen] bounds];
CGFloat x = r.size.height / 2.0;
CGFloat y = r.size.width / 2.0;
self.center = CGPointMake(x, y);
}
return;
}
You are explicitly set the frame of the blocker to the portrait dimensions. It is only being changed when the device is rotated.
Instead, try getting the size from the display to current window when the blocker is being created.

Xcode 5 Your binary is not optimized for iPhone 5 error while validating

I'm running into the Your binary is not optimized for iPhone 5 error:
I tried every solution suggested in the other questions but nothing works. To summarize:
I have the Default-568h#2x.png image with a size of 640 × 1136 in the root directory of the project, where project_name.xcodeproj is.
Following one advice, I added Default.png (640 × 1136) and Default~iphone.png (640 × 960) to the same directory. Didn't work.
I am using an asset catalog with the proper sizes in place.
Here's the strangest part: this is a version 1.1 of the application. I'm using the same .xcodeproj with the same images. It validated with no issues the first time, but now it doesn't. Any ideas?
Using the image asset global to control if the image is correct, and see if there is the warning.
For the future is better using with last Xcode a storyboard screen:
To turn your app in universal mode:
add a storybord or using a StoryBorad in Auto Layout mode.
To use multiple storyboard you can use this in your AppDelegate inside a application didFinishLaunchingWithOptions:
#pragma mark - Universal storyboard.
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone){
UIStoryboard *storyBoard;
CGSize result = [[UIScreen mainScreen] bounds].size;
CGFloat scale = [UIScreen mainScreen].scale;
result = CGSizeMake(result.width *scale, result.height *scale);
if(result.height <= 960){
storyBoard = [UIStoryboard storyboardWithName:#"iPhone4" bundle:nil];
UIViewController *initViewController = [storyBoard instantiateInitialViewController];
[self.window setRootViewController:initViewController];
}
}
You can add all resolution iPhone 4s / 5 (s/c) 6 and 6 Plus
In your <AppName>-Prefix.pch define all resolutions like this:
#define IsIphone5 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )
#define IsIphone4 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )480 ) < DBL_EPSILON )
Then call the function in your project, for example one scrollview for iPhone 4/5 and iPad:
- (void)spiegaScroll{
if (IsIphone5){
CGRect scrollFrame;
scrollFrame.origin = myScroll.frame.origin;
scrollFrame.size = CGSizeMake(320, 568);
spiega.frame = scrollFrame;
[spiega setContentSize:CGSizeMake(320, 1100)];
myScroll.scrollEnabled = YES;
myScroll.pagingEnabled = NO;
myScroll.clipsToBounds = NO;
} else if (IsIphone4) {
CGRect scrollFrame;
scrollFrame.origin = myScroll.frame.origin;
scrollFrame.size = CGSizeMake(320, 480);
spiega.frame = scrollFrame;
[spiega setContentSize:CGSizeMake(320, 1100)];
myScroll.scrollEnabled = YES;
myScroll.pagingEnabled = NO;
myScroll.clipsToBounds = NO;
} else {
//the rest is iPad in this case
CGRect scrollFrame;
scrollFrame.origin = myScroll.frame.origin;
scrollFrame.size = CGSizeMake(768, 1024);
spiega.frame = scrollFrame;
[spiega setContentSize:CGSizeMake(768, 2094)];
myScroll.scrollEnabled = YES;
myScroll.pagingEnabled = NO;
myScroll.clipsToBounds = NO;
}
}
Hope this help you for now or for your future apps ;)
Check wheter the images are added to target files
In your plist file set the value for your images in the icon set dictionary.
Having same issue. finally i found solution from Iphone 5 Launch Image Problem
please make sure the 568h file is in PNG format? Also make sure that you provided support for iphone 5 for all your screens? Only adding Default-568h#2x.png is not gaurantee for iphone 5 support. You have to check for framing of all your view for iphone 3.5" and 4" device.
Well, looks like the problem went away once I upgraded to xCode 6. The app validated with no issues.

Underscan issue with iPhone 5 Lightning HDMI adapter

I am trying to mirror what's on my iPhone to an external display but I can't remove the underscan. All my searches for an answer lead back to "overscanCompensation". Since this is a property of UIScreen, I'm not sure where to add it if I'm not explicitly creating a new UIScreen as mirroring is now automatic.
Auto-mirroring through Lightning HDMI adapter screenshot:
http://blog.axelgimenez.net/dp7-capture-underscan-issue-1.jpg
The other option is to create a UIScreen when a new display is detected. Please see the code below and note that I did use "overscanCompensation = 3". Unfortunately, it doesn't work for me. I've tried all the other overscanCompensation options with no luck.
- (void)checkForExistingScreenAndInitializeIfPresent
{
if ([[UIScreen screens] count] > 1)
{
// Get the screen object that represents the external display.
UIScreen *secondScreen = [[UIScreen screens] objectAtIndex:1];
secondScreen.overscanCompensation = 3;
// Get the screen's bounds so that you can create a window of the correct size.
UIScreenMode *screenMode = [[secondScreen availableModes] lastObject];
CGRect screenBounds = (CGRect){.size = screenMode.size};
self.secondWindow = [[UIWindow alloc] initWithFrame:screenBounds];
self.secondWindow.screen = secondScreen;
// Set up initial content to display...
self.secondWindow.backgroundColor = [UIColor redColor];
// Show the window.
self.secondWindow.hidden = NO;
}
}
Here's the screenshot of the display that the code above creates:
http://blog.axelgimenez.net/dp7-capture-underscan-issue-2.jpg
Same issue of underscan. Any help is greatly appreciated.
FYI - Using the Lightning to HDMI adapter, I connected my iPhone 5 to a SmallHD dp7 monitor. The monitor lets me take screen captures. The underscan also appears when I plug into my TV.

How can I resize a complete view in iOS - from iPad to iPhone with all content proportionally?

I have a view optimized for an iPad. I want to show exactly this same view on an iPhone (yes, I know that the view will be small - this is ok in this case. Black bars on the left and right because of the aspect ratio difference are ok as well).
How can I scale the iPad view for display on iPhone screen? With all content resized proportionally, including fonts, tables, images?
Just define macros
#define X_WIDTH 320/768
#define Y_HEIGHT 480/1024
Multiply all your x and width parameter with X_WIDTH and all your y and height parameters with Y_HEIGHT
Or more generalized is you define variables like
CGRect screenSize = [[UIScreen mainScreen] bounds];
float x_width = screenSize.widht/768;
float y_height = screenSize.height/1024;
How about using the feature of Interface builder to help you through this!!
Make two XIB files, such as, WebView_iPhoneVC and WebView_iPadVC, and set the webview autoresizing for the view in Interface Builder.
Call the XIB's condionally,
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
WebView_iPhoneVC *webviewVC_iPhone = [[WebView_iPhoneVC alloc] initWithNibName:#"WebView_iPhoneVC" bundle:nil];
[self.navigationController pushViewController:webviewVC_iPhone animated:YES];
[webviewVC_iPhone release];
}
else {
WebView_iPadVC *webviewVC_iPadVC = [[WebView_iPadVC alloc] initWithNibName:#"WebView_iPadVC" bundle:nil];
[self.navigationController pushViewController:webviewVC_iPadVC animated:YES];
[webviewVC_iPadVC release];
}

Resources