45

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: When I set size in attribute inspector to 3.5

it looks in iphone-5. There is a space below the buttons: And this is how it looks in simulator for 3.5 inch device

If I set size 4 inch in interface builder. You can see that bottom buttons are not visible in iphone-4. If I set size 3.5 inch in interface builder

So you will ask what are the settings I am using. Here are they:

enter image description here enter image description here enter image description here

user739711
  • 1,842
  • 1
  • 25
  • 30

14 Answers14

38
  1. 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;
    
  2. 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;
      }
    
  3. Open YouProject-Prefix.pch file and import your category here

  4. 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 :-)

\

Waseem Shah
  • 2,219
  • 23
  • 23
20

Try adding this to all your controllers which need to support iPhone 5:

- (void) loadView
{
    [super loadView];
    self.view.frame = [UIScreen mainScreen].bounds;
}
ivanzoid
  • 5,952
  • 2
  • 34
  • 43
11

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

enter image description here

Navnath Godse
  • 2,233
  • 2
  • 23
  • 32
  • @bijan...What problem you are facing ? – Navnath Godse May 20 '13 at 17:37
  • 5
    After setting the Size property to "None", i still get a iPhone 4 height view on iPhone 5 Simulator. – bijan May 20 '13 at 19:21
  • This only changes the outer wrapper, which really won't help most people who put *stuff* inside the view (they don't leave the view empty, it has text fields, buttons, etc, and this answer doesn't cover that). – trusktr Aug 01 '13 at 23:42
  • To resize or repositioning the UIButton/UILabel you need to select that specific item, then from "Resolve Auto Layout Issue"(positioned at the bottom right corner,third from the left among four buttons) press the "Add Missing Constraints in View". – Shad Apr 22 '14 at 03:13
6

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.

Diarrhio
  • 190
  • 3
  • 6
  • 1
    unbelievable, exactly the same case for me. i had a warning in xcode about the missing Default-568h@2x.png file and xcode even offered to add it for me. after that all was golden. – EarlGrey Aug 20 '14 at 21:48
3

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.

MaheshShanbhag
  • 1,484
  • 15
  • 14
3

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;
}
Ed Trujillo
  • 1,371
  • 11
  • 9
1

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.

Shinigamae
  • 854
  • 3
  • 18
  • 35
1

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);
}
Navnath Godse
  • 2,233
  • 2
  • 23
  • 32
Chris Alan
  • 1,426
  • 14
  • 14
1

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.

BigCheesy
  • 1,128
  • 8
  • 14
0

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.

NSGod
  • 22,699
  • 3
  • 58
  • 66
rooster117
  • 5,502
  • 1
  • 21
  • 19
0
  • 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.

Nirav Bhatt
  • 6,940
  • 5
  • 45
  • 89
0

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.

Chris Fox
  • 641
  • 6
  • 10
0

If you dont want use two xib and interested to do using Autosizing here

the1pawan
  • 1,194
  • 9
  • 26
-1

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
}
Poorva
  • 130
  • 6