Developing for iPhone 4 and iPhone 5 in one application - iphone

I have been away from iOS development for a bit and I am at road block.
One of my apps has a UIImageView graphic and then I have buttons that overlay the visuals. I am able to get everything working except for the autolayout.
If I set my nib to 3.5 and run the simulator in 3.5 mode everything works great. If I run it in 4.0 mode, the buttons all shift. This applies with the reverse of this also.
I'm not sure how to get around the buttons that move. Is there a way or should there be 2 nibs?

If you're not using IB then you would get the size of the view and layout based on that.
I usually use a single value for the verticalOffset (NSInteger) and base Y values on that with different multiples of the value depending on the interface element.
CGRect screenBounds = [[UIScreen mainScreen] bounds];
if (screenBounds.size.height == 568) { // iPhone 5
verticalOffset = 20;
} else {
verticalOffset = 0;
}
if in the future Apple releases a iPhone 5.5 with a 768 pixel height (I jest.. ha!)
You would only need to add in a new verticalOffset value and the view would instamagically fill the new size.
CGRect screenBounds = [[UIScreen mainScreen] bounds];
if (screenBounds.size.height == 768) { // iPhone 5.5
verticalOffset = 30;
} else if (screenBounds.size.height == 568) { // iPhone 5
verticalOffset = 20;
} else {
verticalOffset = 0;
}
The easy way for IB/iPhone if you want to support older iOS versions turn OFF autolayout
And turn off auto sizing for the top value.
Layout the view in IB for the iPhone 5 and when you use the iPhone 3.5in all the the interface elements will squeeze into the 3.5in size (make sure you leave enough whitespace when you lay it out in the taller size)

You can follow this good autolayout tutorial: http://www.raywenderlich.com/20881/beginning-auto-layout-part-1-of-2

Develop in 3.5 inch screen, but enable autoLayout. Go through each item in your view and adjust the auto sizing.
- Select item
- Go down to where the white arrows are by zoom in/out in interface builder. Click the little button that looks like an H.
- This will allow you to adjust the adjustments for each item

Related

Best way to manage screen height differences on iPhone 5 and others

What is the best way to manage screen height differences between iPhone 5 and other versions?
If we use the storyboard or xib it will resize it accordingly. But if the whole view is build programmatically, how we take care of this issue.
Currently what I do is that I get the whole screen height and set the rest of the UI elements according to this height like height * .7 or height *.5 ..
But still it didn’t give me the best experience.
Thanks,
You can check for [UIScreen mainScreen].bounds.size.height(may be, use it as a static method or do a #define) and do the screen design based on the screen height. Another way is to use the view.autoresizingMask property to adjust the views.
for eg:-
view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
If you are building for iOS 6, you can use Auto layout features.
In your viewDidLoad just check for screen size Like this...
- (void)viewDidLoad
{
[super viewDidLoad];
CGRect screenBounds = [[UIScreen mainScreen] bounds];
if (screenBounds.size.height == 568)
{
//iPhone 5
}
else
{
// iPhone 4
}
}

How to make xib compatible with both iphone 5 and iphone 4 devices

I am trying to layout my xib so that layout fits in both iphone 5 (4 inches retina) and 3.5 devices.
Because I have to support IOS-5 I cannot use autolayout. I have to use springs and Struts.
I tried everything in interface-builder. But either my view is going beyond the bottom of iphone-3.5-inch or not filling completely the iphone-4-inch-retina.
Can someone give a hint how to actually make an xib compatible to both the devices?
For more clarity I am adding screenshots:
When I set size 3.5 in attribute inspector:
it looks in iphone-5. There is a space below the buttons:
If I set size 4 inch in interface builder. You can see that bottom buttons are not visible in iphone-4.
So you will ask what are the settings I am using. Here are they:
You add new category for UIviewController and add this code in .h file
- (id)initWithNibNameforIphone4:(NSString *)nibNameOrNil4 NibNameforIphone5:(NSString *)nibNameOrNil5 NibNameforIpad:(NSString *)nibNameOrNilpad bundle:(NSBundle *)nibBundleOrNil;
Add this code in your .m file
- (id)initWithNibNameforIphone4:(NSString *)nibNameOrNil4 NibNameforIphone5:(NSString *)nibNameOrNil5 NibNameforIpad:(NSString *)nibNameOrNilpad bundle:(NSBundle *)nibBundleOrNil
{
if (self = [super init])
{
self = [self initWithNibName:[self CheckDeviceIphone4:nibNameOrNil4 Iphone5:nibNameOrNil5 Ipad:nibNameOrNilpad] bundle:nibBundleOrNil];
}
return self;
}
-(NSString *)CheckDeviceIphone4:(NSString *)iphone4 Iphone5:(NSString *)iphone5 Ipad:(NSString *)ipad {
return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) ? ipad :([[UIScreen mainScreen] bounds].size.height == 568) ? iphone5 :iphone4;
}
Open YouProject-Prefix.pch file and import your category here
now you just use this in all over project like this
self.firstView=[[firstView alloc]initWithNibNameforIphone4:#"firstView4" NibNameforIphone5:#"firstView" NibNameforIpad:#"firstViewIpad" bundle:[NSBundle mainBundle]];
thanks and any question then comment and dont forget to upvote :-)
\
Try adding this to all your controllers which need to support iPhone 5:
- (void) loadView
{
[super loadView];
self.view.frame = [UIScreen mainScreen].bounds;
}
Just set view size to None using Interface-builder
It will take view size at runtime, just you need to take care of origin and autosizing for each element(UILabel, UIImage, etc.) in the view.
Interface-builder(XIB) -> Attribute Inspector -> Simulated Metrics - Size: None
I was struggling with this today, and no matter what I did, my views were always showing up as 320x480, even when running on the retina 4" simulator. Even [UIScreen mainScreen].bounds was returning 320x480!
I found that adding the Default-568h#2x.png launch image was the key to getting iOS to recognize my app as 'retina 4" ready'. Once I did that, I found had to do nothing else to get nibs to automatically size without the black bars. No need to have two separate xibs, change settings in Interface Builder, overriding loadView, etc.
You need not use a different nib for the 3.5 inch and 4 inch devices. Design the app for the 4 inch device and set the AutoResizingMask correctly and it should work correctly.
In your case just set the AutoResizingMask to
[view setAutoresizingMask:UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth];
The autoresizing mask places the view correctly to its position in both the devices.
If you go with the solution of using 2 xib files; in your initWithNibName() method simply make a call to super with the different nib name.
I would test on the original 480 height dimension rather than on the 568 height so that the larger xib file is selected when Apple releases a larger screen. In the future, at least the larger xib won't be letter-boxed as much as the smaller one.
// From MainView.m
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
CGSize result = [[UIScreen mainScreen] bounds].size;
if(result.height == 480)
{
// iPhone Classic
self = [super initWithNibName:#"MainView" bundle:nibBundleOrNil];
}
else
{
// iPhone 5 or maybe a larger iPhone ??
self = [super initWithNibName:#"MainView5" bundle:nibBundleOrNil];
}
return self;
}
I have an idea. Let separate your UI into header, body and footer (like website). Then in your code console, locate to Size Inspector and use the Autosizing.
Notice the outside lines of the square, it is your control location against main view. Set the controls (navigation bar, UIImageView, UIButton etc.) in header part and body part attached to Top and the controls (Bookmark, Close etc.) in footer to Bottom.
Everytime you run, the controls will attach to their autosizing settings. You will have a space between header/body and footer on iPhone 5 but I think it's fine.
Define below line and check condition based on device.
#define IS_IPHONE_5 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 )
if (IS_IPHONE_5) {
btnBookmark.frame=CGRectMake(0, 460, 100, 70);
btnBookmark.frame=CGRectMake(150, 460, 100, 70);
}
else {
btnBookmark.frame=CGRectMake(0, 360, 100, 70);
btnBookmark.frame=CGRectMake(150, 360, 100, 70);
}
I was having an issue with 3.5" vs. 4" as well, and I misunderstood what was wrong so I wanted to document it here incase it helps anyone.
If you are trying to access self.view.frame it will not be correctly reported until viewDidAppear or some similar event. If you try to access self.view.frame from within viewDidLoad then you can be reported the dimensions of the frame before autosizing takes place.
In your storyboard, click 'Show file inspector'.
Under Interface builder document->Document versioning, select Deployment=iOS 5 (or your choice).
If this doesn't work, you need to work with each of your views.
Select them. Under Attributes inspector for each of them, under View section, see Mode attribute. Set this to 'Redraw'.
If even that doesn't give satisfactory result, set the view size to the smallest of all the version you are going to use. And set the Mode attribute = 'Scale to fill'.
Programmatically, Mode attribute is view.contentmode property.
Without using autolayout you may need to handle a lot of things in code. I assume most of your layout can work well with springs and struts but some UI elements can't so just manually set the frames of certain objects according to the size of your view is necessary.
ivanzoid's snippet above that queries for the whole screen size does the trick so long as you remember to subtract the offsets for navigation and toolbars (totalling 64 under most conditions).
It's the view height that needs to be adjusted; springs and struts otherwise take care of it.
Retesting my app on the iPhone 5 I only had to do this on one screen with some runtime control position adjustments. Every other case is handled by XIB defaults.
If you dont want use two xib and interested to do using Autosizing here
If your UI is too complicated and contains too many UIControls , then I suggest to do the following in viewDidLoad():
NSLog(#"Iphone %f ",[[UIScreen mainScreen] bounds].size.height);
if ([[UIScreen mainScreen] bounds].size.height == 568)
{
//design frames of your controls accordingly add add the controls as subview to
self.view
//this is iphone 5 xib
} else
{
//design frames of your controls accordingly add add the controls as subview to
self.view
// this is iphone 4 xib
}

iPhone 5 size support [duplicate]

The new iPhone 5 display has a new aspect ratio and a new resolution (640 x 1136 pixels).
What is required to develop new or transition already existing applications to the new screen size?
What should we keep in mind to make applications "universal" for both the older displays and the new widescreen aspect ratio?
Download and install latest version of Xcode.
Set a Launch Screen File for your app (in the general tab of your target settings). This is how you get to use the full size of any screen, including iPad split view sizes in iOS 9.
Test your app, and hopefully do nothing else, since everything should work magically if you had set auto resizing masks properly, or used Auto Layout.
If you didn't, adjust your view layouts, preferably with Auto Layout.
If there is something you have to do for the larger screens specifically, then it looks like you have to check height of [[UIScreen mainScreen] bounds] as there seems to be no specific API for that. As of iOS 8 there are also size classes that abstract screen sizes into regular or compact vertically and horizontally and are recommended way to adapt your UI.
If you have an app built for iPhone 4S or earlier, it'll run letterboxed on iPhone 5.
To adapt your app to the new taller screen, the first thing you do is to change the launch image to: Default-568h#2x.png. Its size should be 1136x640 (HxW). Yep, having the default image in the new screen size is the key to let your app take the whole of new iPhone 5's screen.
(Note that the naming convention works only for the default image. Naming another image "Image-568h#2x.png" will not cause it to be loaded in place of "Image#2x.png". If you need to load different images for different screen sizes, you'll have to do it programmatically.)
If you're very very lucky, that might be it... but in all likelihood, you'll have to take a few more steps.
Make sure, your Xibs/Views use auto-layout to resize themselves.
Use springs and struts to resize views.
If this is not good enough for your app, design your xib/storyboard
for one specific screen size and reposition programmatically for the
other.
In the extreme case (when none of the above suffices), design the two Xibs and load the appropriate one in the view controller.
To detect screen size:
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
    CGSize result = [[UIScreen mainScreen] bounds].size;
    if(result.height == 480)
{
// iPhone Classic
    }
    if(result.height == 568)
{
// iPhone 5
    }
}
The only really required thing to do is to add a launch image named "Default-568h#2x.png" to the app resources, and in general case (if you're lucky enough) the app will work correctly.
In case the app does not handle touch events, then make sure that the key window has the proper size. The workaround is to set the proper frame:
[window setFrame:[[UIScreen mainScreen] bounds]]
There are other issues not related to screen size when migrating to iOS 6. Read iOS 6.0 Release Notes for details.
Sometimes (for pre-storyboard apps), if the layout is going to be sufficiently different, it's worth specifying a different xib according to device (see this question - you'll need to modify the code to deal with iPhone 5) in the viewController init, as no amount of twiddling with autoresizing masks will work if you need different graphics.
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
NSString *myNibName;
if ([MyDeviceInfoUtility isiPhone5]) myNibName = #"MyNibIP5";
else myNibName = #"MyNib";
if ((self = [super initWithNibName:myNibName bundle:nibBundleOrNil])) {
...
This is useful for apps which are targeting older iOS versions.
Here you can find a nice tutorial (for MonoTouch, but you can use the information for Non-MonoTouch-projects, too):
http://redth.info/get-your-monotouch-apps-ready-for-iphone-5-ios-6-today/
Create a new image for your splash/default screen (640 x 1136 pixel) with the name "Default-568h#2x.png"
In the iOS Simulator, go to the Hardware -> Device menu, and select "iPhone (Retina 4-inch)"
Create other images, e.g. background images
Detect iPhone 5 to load your new images:
public static bool IsTall
{
get {
return UIDevice.currentDevice.userInterfaceIdiom
== UIUserInterfaceIdiomPhone
&& UIScreen.mainScreen.bounds.size.height
* UIScreen.mainScreen.scale >= 1136;
}
}
private static string tallMagic = "-568h#2x";
public static UIImage FromBundle16x9(string path)
{
//adopt the -568h#2x naming convention
if(IsTall())
{
var imagePath = Path.GetDirectoryName(path.ToString());
var imageFile = Path.GetFileNameWithoutExtension(path.ToString());
var imageExt = Path.GetExtension(path.ToString());
imageFile = imageFile + tallMagic + imageExt;
return UIImage.FromFile(Path.Combine(imagePath,imageFile));
}
else
{
return UIImage.FromBundle(path.ToString());
}
}
It's easy for migrating iPhone5 and iPhone4 through XIBs.........
UIViewController *viewController3;
if ([[UIScreen mainScreen] bounds].size.height == 568)
{
UIViewController *viewController3 = [[[mainscreenview alloc] initWithNibName:#"iphone5screen" bundle:nil] autorelease];
}
else
{
UIViewController *viewController3 = [[[mainscreenview alloc] initWithNibName:#"iphone4screen" bundle:nil] autorelease];
}
I solve this problem here. Just add ~568h#2x suffix to images and ~568h to xib's. No needs more runtime checks or code changes.
I had added the new default launch image and (in checking out several other SE answers...) made sure my storyboards all auto-sized themselves and subviews but the retina 4 inches still letterboxed.
Then I noticed that my info plist had a line item for "Launch image" set to "Default.png", which I thusly removed and magically letterboxing no longer appeared. Hopefully, that saves someone else the same craziness I endured.
I guess, it is not going to work in all cases, but in my particular project it avoided me from duplication of NIB-files:
Somewhere in common.h you can make these defines based off of screen height:
#define HEIGHT_IPHONE_5 568
#define IS_IPHONE ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
#define IS_IPHONE_5 ([[UIScreen mainScreen] bounds ].size.height == HEIGHT_IPHONE_5)
In your base controller:
- (void)viewDidLoad
{
[super viewDidLoad];
if (IS_IPHONE_5) {
CGRect r = self.view.frame;
r.size.height = HEIGHT_IPHONE_5 - 20;
self.view.frame = r;
}
// now the view is stretched properly and not pushed to the bottom
// it is pushed to the top instead...
// other code goes here...
}
In a constants.h file you can add these define statements:
#define IS_IPAD UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad
#define IS_IPHONE UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone
#define IS_WIDESCREEN (fabs((double)[[UIScreen mainScreen] bounds].size.height - (double)568) < DBL_EPSILON)
#define IS_IPHONE_5 (!IS_IPAD && IS_WIDESCREEN)
To determine if your app can support iPhone 5 Retina use this:
(This could be more robust to return the type of display, 4S Retina, etc., but as it is written below, it just returns if the iPhone supports iOS5 Retina as a YES or NO)
In a common ".h" file add:
BOOL IS_IPHONE5_RETINA(void);
In a common ".m" file add:
BOOL IS_IPHONE5_RETINA(void) {
BOOL isiPhone5Retina = NO;
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
if ([UIScreen mainScreen].scale == 2.0f) {
CGSize result = [[UIScreen mainScreen] bounds].size;
CGFloat scale = [UIScreen mainScreen].scale;
result = CGSizeMake(result.width * scale, result.height * scale);
if(result.height == 960){
//NSLog(#"iPhone 4, 4s Retina Resolution");
}
if(result.height == 1136){
//NSLog(#"iPhone 5 Resolution");
isiPhone5Retina = YES;
}
} else {
//NSLog(#"iPhone Standard Resolution");
}
}
return isiPhone5Retina;
}
First of all create two xibs and attach all delegates,main class to the xib and then u can put in this condition mentioned below in your appdelegate.m file in
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
if ([[UIScreen mainScreen] bounds].size.height == 568)
{
self.ViewController = [[ViewController alloc] initWithNibName:#"ViewControlleriphone5" bundle:nil];
}
else
{
self.ViewController = [[ViewController alloc] initWithNibName:#"ViewControlleriphone4" bundle:nil];
}
you can use it any where in the program depending upon your requirements even in your ViewController classes. What matters the most is that you have created two xib files separate for iphone 4(320*480) and iphone 5(320*568)
Try the below method in a singleton class:
-(NSString *)typeOfDevice
{
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
CGSize result = [[UIScreen mainScreen] bounds].size;
if(result.height == 480)
{
return #"Iphone";
}
if(result.height == 568)
{
return #"Iphone 5";
}
}
else{
return #"Ipad";;
}
return #"Iphone";
}
You can use the Auto Layout feature and create the design using iPhone 5 screen resolution and it will work for the both 4" and 3.5" devices, but in this case you should have a enough knowledge of layout manager.
Checking bounds with 568 will fail in landscape mode. iPhone 5 launches only in portrait mode but if you want to support rotations then the iPhone 5 "check" will need to handle this scenario as well.
Here's a macro which handles orientation state:
#define IS_IPHONE_5 (CGSizeEqualToSize([[UIScreen mainScreen] preferredMode].size, CGSizeMake(640, 1136)))
The use of the 'preferredMode' call is from another posting I read a few hours ago so I did not come up with this idea.
First show this image. In that image you show warning for Retina 4 support so click on this warning and click on add so your Retina 4 splash screen automatically add in your project.
and after you use this code :
if([[UIScreen mainScreen] bounds].size.height == 568)
{
// For iphone 5
}
else
{
// For iphone 4 or less
}
I never faced such an issue with any device as I've had one codebase for all, without any hardcoded values. What I do is to have the maximum sized image as resource instead of one for each device. For example, I would have one for retina display and show it as aspect fit so it will be views as is on every device.
Coming to deciding the frame of button, for instance, at run time. For this I use the % value of the patent view, example , if I want the width to be half of parent view take 50 % of parent and same applies for height and center.
With this I don't even need the xibs.
You can use this define to calculate if you are using the iPhone 5 based on screen size:
#define IS_IPHONE_5 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )
then use a simple if statement :
if (IS_IPHONE_5) {
// What ever changes
}
Peter, you should really take a look at Canappi, it does all that for you, all you have to do is specify the layout as such:
button mySubmitButton 'Sumbit' (100,100,100,30 + 0,88,0,0) { ... }
From there Canappi will generate the correct objective-c code that detects the device the app is running on and will use:
(100,100,100,30) for iPhone4
(100,**188**,100,30) for iPhone 5
Canappi works like Interface Builder and Story Board combined, except that it is in a textual form. If you already have XIB files, you can convert them so you don't have to recreate the entire UI from scratch.
You can manually check the screen size to determine which device you're on:
#define DEVICE_IS_IPHONE5 ([[UIScreen mainScreen] bounds].size.height == 568)
float height = DEVICE_IS_IPHONE5?568:480;
if (height == 568) {
// 4"
} else {
// 3"
}
You could add this code:
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone){
if ([[UIScreen mainScreen] respondsToSelector: #selector(scale)]) {
CGSize result = [[UIScreen mainScreen] bounds].size;
CGFloat scale = [UIScreen mainScreen].scale;
result = CGSizeMake(result.width * scale, result.height * scale);
if(result.height == 960) {
NSLog(#"iPhone 4 Resolution");
}
if(result.height == 1136) {
NSLog(#"iPhone 5 Resolution");
}
}
else{
NSLog(#"Standard Resolution");
}
}
This is a real universal code, you can create 3 different story board:
Set your project Universal mode, and set your main story iPhone with the iPhone5 storyboard and the ipad main with iPad target storyboard, now add new storyboard target for iphone and modify the resolution for iphone 4s or less now implement your AppDelegate.m
iPhone4/4s (is the same for 3/3Gs) one for iPhone5 and make the project universal, with a new Storyboard target for iPad, now in to AppDelegate.m under the didFinishLaunching add this code:
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);
//----------------HERE WE SETUP FOR IPHONE4/4s/iPod----------------------
if(result.height == 960){
storyBoard = [UIStoryboard storyboardWithName:#"iPhone4_Storyboard" bundle:nil];
UIViewController *initViewController = [storyBoard instantiateInitialViewController];
[self.window setRootViewController:initViewController];
}
//----------------HERE WE SETUP FOR IPHONE3/3s/iPod----------------------
if(result.height == 480){
storyBoard = [UIStoryboard storyboardWithName:#"iPhone4_Storyboard" bundle:nil];
UIViewController *initViewController = [storyBoard instantiateInitialViewController];
[self.window setRootViewController:initViewController];
}
}
return YES;
}
So you have created a Universal app for iPhone 3/3Gs/4/4s/5 All gen of iPod, and All type of iPad
Remember to integrate all IMG with myImage.png and myImage#2x.png
According to me the best way of dealing with such problems and avoiding couple of condition required for checking the the height of device, is using the relative frame for views or any UI element which you are adding to you view for example: if you are adding some UI element which you want should at the bottom of view or just above tab bar then you should take the y origin with respect to your view's height or with respect to tab bar (if present) and we have auto resizing property as well. I hope this will work for you
Rather than using a set of conditionals you can resize your view automatically using the screen size.
int h = [[UIScreen mainScreen] bounds].size.height;
int w = [[UIScreen mainScreen] bounds].size.width;
self.imageView.frame = CGRectMake(20, 80, (h-200), (w-100));
In my case I want a view that fills the space between some input fields at the top and some buttons at the bottom, so fixed top left corner and variable bottom right based on screen size. My app fills the image view with the photo taken by the camera so I want all the space I can get.
If you need to convert an already existing app to universal, you need to select corresponding xib file->show Utilities-> Show Size inspector.
In Size inspector you can see Autosizing, by using this tool you can convert to existing iOS App.
Using xCode 5, select "Migrate to Asset Catalog" on Project>General.
Then use "Show in finder" to find your launch image, you can dummy-edit it to be 640x1136, then drag it into the asset catalog as shown in the image below.
Make sure that both iOS7 and iOS6 R4 section has an image that is 640x1136. Next time you launch the app, the black bars will disappear, and your app will use 4 inch screen
Point worth notice - in new Xcode you have to add this image file Default-568h#2x.png to assets
Use the Auto Layout feature for views. It will adjust automatically to all resolutions.
Create two xibs for a controller having controller name with suffix either ~iphone or ~ipad. At compile time, Xcode will take the right xib based on the device.
Use size classes, if you want to create a single xib for both iPhone and iPad, if the view is simple enough to port to iPhone and iPad.
There is a slight problem when testing on both iOS device and iOS Simulator. It appears that simulator (XCode 6.0.1) gives switched values for width and height in [[UIScreen mainScreen] bounds].size depending on a device orientation.
So this might be a problem when determinating the right physical screen size. This code helps also to distinct all 2014. iPhone model generations:
iPhone4s
iPhone5 (and iPhone5s)
iPhone6 (and iPhone6+)
It can also be easily changed to make the distinction between e.g. iPhone6 from iPhone6+.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
CGSize iOSDeviceScreenSize = [[UIScreen mainScreen] bounds].size;
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)
{
if (iOSDeviceScreenSize.width > 568 || // for iOS devices
iOSDeviceScreenSize.height > 568) // for iOS simulator
{ // iPhone 6 and iPhone 6+
// Instantiate a new storyboard object using the storyboard file named Storyboard_iPhone6
storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone6" bundle:nil];
NSLog(#"loaded iPhone6 Storyboard");
}
else if (iOSDeviceScreenSize.width == 568 || // for iOS devices
iOSDeviceScreenSize.height == 568) // for iOS simulator
{ // iPhone 5 and iPod Touch 5th generation: 4 inch screen (diagonally measured)
// Instantiate a new storyboard object using the storyboard file named Storyboard_iPhone5
storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone5" bundle:nil];
NSLog(#"loaded iPhone5 Storyboard");
}
else
{ // iPhone 3GS, 4, and 4S and iPod Touch 3rd and 4th generation: 3.5 inch screen (diagonally measured)
// Instantiate a new storyboard object using the storyboard file named Storyboard_iPhone4
storyboard = [UIStoryboard story boardWithName:#"MainStoryboard_iPhone" bundle:nil];
NSLog(#"loaded iPhone4 Storyboard");
}
}
else if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad)
{ // The iOS device = iPad
storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPadnew" bundle:nil];
NSLog(#"loaded iPad Storyboard");
}
// rest my code
}
I would suggest to use Autoresizing Mask in your applications according to your UI interface, it saves a lot of trouble and is better than making different UI for iPhone 4 and 5 screens.

How to set the frame for iphone 4 and iphone 5 in ios6

I want to update my application to ios 6. so how to set the frame size comfortable both iphone 4 and iphone 5?
I can using Calculate the Screen size then to adjust the height of the view like using following method
+(CGFloat)heightOf:(CGFloat)heightValue{
CGRect applicationFrame = [[UIScreen mainScreen] applicationFrame];
//NSLog(#"applciation Frame height = %f",applicationFrame.size.height);
CGFloat heightRatio = (heightValue/480)*100;
CGFloat height = (applicationFrame.size.height * heightRatio)/100;
return height;
}
then I am using like as
UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0,[Height heightOf:385], 320, 220)];
and so.
Thanks for your Replies
There is more than one way of handling the situation.
1> One of them is to use auto-resizing properly.
2>Another way is to use the new Auto Layout functionality, but then again this will only be supported for iOS 6.
3>You can create separate nib's for each view one for iphone 4 and iphone 5 and depending on which device it is running, you can switch the used .xib files.
Best way right now to go about is to use, auto resizing properly.
For more you can go through these
1> Supporting iOS 4.3 to iOS 6.0
2> What is the best way for supporting both screen resolution of iPhone4 and iPhone5 ? - Auto layout in only iOS6
Following code check for the iPhone 5 and other device
#define IS_IPHONE ( [[[UIDevice currentDevice] model] isEqualToString:#"iPhone"] )
#define IS_IPOD ( [[[UIDevice currentDevice ] model] isEqualToString:#"iPod touch"] )
#define IS_HEIGHT_GTE_568 [[UIScreen mainScreen ] bounds].size.height >= 568.0f
#define IS_IPHONE_5 ( IS_IPHONE && IS_HEIGHT_GTE_568 )
And check for more detail refer the question.
u can check the device type link or you can check if the view frame larger than the normal one in iPhone 4/4s then resize your frame
note: i'm use the second way and it is work
AutoLayout did not work out so well for me. My app has several elements which need to be spaced out evenly.
A Quick fix solution (not good practice) is to assign coordinates individually upon the screen height check.
(BTW that is a good tutorial. Shame Apple still haven't come up with anything substantial for IOS).
If You have several element on your screen, then I believe you'll have to re-place them individually
CGFloat height = [UIscreen mainScreen].bounds.size.height;
if(height==568.00){
self.imageName.frame = CGRectMake(x,y,width,height);
...
}
For a modal or floating screen which appears in the center of window, you could try this:
self.imgBadgeArea.frame = CGRectMake(self.view.bounds.size.width/2- self.imgBadgeArea.bounds.size.width/2, self.view.bounds.size.height/2 - self.imgBadgeArea.bounds.size.height/2, self.imgBadgeArea.bounds.size.width, self.imgBadgeArea.bounds.size.height);
Works for both 3.5 and 4 inches.

iPhone Landscape-Only Utility-Template Application

I'm trying to create an iPhone application that is always in landscape mode, using the Utility application template. Here's what I did:
Create a new iPhone application project, using the Utility Application template
In Interface Builder, rotate all the views 90 degrees.
In Interface Builder, add a label to the middle of the MainView. Stretch it all the way across the view, set the alignment to centered, and set the autosizing springs so that it can stretch horizontally.
In Info.plist, add the key "UIInterfaceOrientation" with value "UIInterfaceOrientationLandscapeRight"
In the controller classes, change the shouldAutorotateToInterfaceOrientation methods to "return (interfaceOrientation == UIInterfaceOrientationLandscapeRight) || (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);"
Run the app.
When I launch my app, it comes up in landscape orientation, but the main view only covers the top half of the display, and it is stretched horizontally. I get the same results in both the simulator and on an actual device. I've seen it with versions 2.2 and 2.2.1 of the SDK.
I have been able to work around the problem by adding the following step to the above:
Add "self.view.autoresizesSubviews = NO;" to RootViewController's viewDidLoad method after "[super viewDidLoad];".
If I do this, then it works as expected. But this feels like a hack. Why should this be necessary?
I don't think it is a transformation issue. All elements are drawn in the proper orientation and with the proper scaling. The problem seems to be that the bounds rectangles of the main view gets funky. It looks like the height of the main view is being cut by a little more than half, and the width is being increased by about 50%.
If I do the exact same set of steps using the View-based Application template instead of Utility, then everything works as expected. So I'm pretty sure the problem is specific to how a Utility application manages its views.
Anybody understand what's going on here?
I was going to say that setting this key does not rotate your interface; you still need to lay out your content in landscape mode and do the appropriate rotation using CFAffineTransform - see "Launching in Landscape Mode" in iPhone OS Programming Guide. Going to find the reference for you, I found this comment: "To launch a view controller–based application in landscape mode in versions of iPhone OS prior to v2.1, you need to apply a 90 degree rotation to the transform of the application’s root view in addition to all the preceding steps. Prior to iPhone OS 2.1, view controllers did not automatically rotate their views based on the value of the UIInterfaceOrientation key. This step is not necessary in iPhone OS 2.1 and later, however."
So if you're running pre-2.1, you need to add this code to your viewDidLoad method in your view controller. (Otherwise, can you post some code?)
-(void)viewDidLoad
// After loading the view, transform the view so that the co-ordinates are right for landscape
// As described in iPhone Application Programming Guide
// Weird, I'm sure this used to be needed, but it doesn't now. The one in CardScrollViewController is needed though.
{
[super viewDidLoad];
CGAffineTransform transform = self.view.transform;
CGPoint center = CGPointMake(kScreenHeight / 2.0, kScreenWidth / 2.0);
// Set the center point of the view to the center point of the window's content area.
self.view.center = center;
// Rotate the view 90 degrees around its new center point.
transform = CGAffineTransformRotate(transform, (M_PI / 2.0));
self.view.transform = transform;
}
Jane describes the setting of UIInterfaceOrientation to UIInterfaceOrientationLandscapeRight (or UIInterfaceOrientationLandscapeLeft), and the rotation settings recommended in the documentation, but I used a slightly different block of code (to the same end) in my root view controller:
- (void)loadView
{
UIView *primaryView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
primaryView.backgroundColor = [UIColor clearColor];
// Start in landscape orientation, and stay that way
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (orientation == UIInterfaceOrientationLandscapeRight)
{
CGAffineTransform transform = primaryView.transform;
// Use the status bar frame to determine the center point of the window's content area.
CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
CGRect bounds = CGRectMake(0, 0, statusBarFrame.size.height, statusBarFrame.origin.x);
CGPoint center = CGPointMake(60.0, bounds.size.height / 2.0);
// Set the center point of the view to the center point of the window's content area.
primaryView.center = center;
// Rotate the view 90 degrees around its new center point.
transform = CGAffineTransformRotate(transform, (M_PI / 2.0));
primaryView.transform = transform;
}
self.view = primaryView;
[primaryView release];
}
In addition to that, I implemented the following delegate method in my root view controller:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return ( (interfaceOrientation == UIInterfaceOrientationLandscapeLeft) || (interfaceOrientation == UIInterfaceOrientationLandscapeRight));
}
Finally, I was encountering weird glitches with the Simulator not auto-rotating properly, so I needed to implement the following delegate method in my UIApplicationDelegate:
- (void)application:(UIApplication *)application willChangeStatusBarOrientation:(UIInterfaceOrientation)newStatusBarOrientation duration:(NSTimeInterval)duration;
{
// This prevents the view from autorotating to portrait in the simulator
if ((newStatusBarOrientation == UIInterfaceOrientationPortrait) || (newStatusBarOrientation == UIInterfaceOrientationPortraitUpsideDown))
[application setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO];
}
After all that, my application was able to start in landscape (right) and stay in that orientation under the 2.0 firmware and in the Simulator.
Try setting the orientation property of the view to Landscape in the nib. This property can be found in 4th tab[Attributes Inspector] of Info View of the UIView under Simulated Metrices.