我可以使用两个xib和一个viewcontroller - re:移植到iPhone 5

时间:2012-10-01 18:09:53

标签: uiviewcontroller xib iphone-5

我刚将第一个应用提交到应用商店(yay it was just approved!)。我现在想要更新它以便在更大的iPhone 5屏幕上工作(看起来更好)。除了为更大的屏幕更改布局外,我不打算改变任何其他内容。

注意:我不想让我当前的xib伸展。

是否可以创建两个xib文件(即:将我当前的xib文件复制到主屏幕)并将它们挂钩到视图控制器中并使其具有以便在应用程序启动时,应用程序检测是否有iPhone 5个屏幕或更早的屏幕。然后,根据它是哪个设备,向用户显示不同的屏幕。

我打算让底层应用保持不变。我想要的只是为iPhone 5用户提供一个稍微不同(更高)的屏幕,其中有几个按钮/项目移动到新的布局。否则我不会在界面中添加或删除任何内容。

This SO question/answer显示了如何在iPhone或iPad视图之间切换。 this one也是如此。两者都有帮助,但我不知道如何修改这个用户使用iPhone 5的大屏幕或iPhone 4S及以下的情况。此外,他们假设两个视图控制器。我只想要一个视图控制器,因为在视图控制器逻辑中完全没有变化 - 只有屏幕上对象的位置发生变化,而这一切都在XIB中完成。

我认为答案应该是视图控制器iteslf评估它运行的设备然后呈现适当的xib?是?否?

如果是这样,我该怎么做呢?

3 个答案:

答案 0 :(得分:25)

[修订完整答案:2012年10月7日]

经过重大研究后,我找到了答案,部分依据this SO page (which shows how to detect which iPhone version your app is running on)和部分this SO page (showing how to have two xib's share the same 'File's Owner'。我在The Big Nerd Ranch's excellent iOS Programming text的第10章中找到了拼图的最后一部分(通过loadNibNamed:方法加载单独的xib)。方法如下:

  1. 创建第二个xib(File,New ...,File,选择'User Interface',选择'Empty'并保存。这将创建新的xib。在下面的示例中,我的经典xib(用于3.5“iPhone”被命名为TipMainViewController.xib。我保存了新的iPhone 5 xib,名称为“TipMainViewController-5.xib”

  2. 让新xib的'File'所有者'与现有的xib相同的ViewController。为此,请在新的xib文件中选择“文件所有者”。然后在“Identity Inspector”中选择现有的View Controller作为Custom Class。在我的例子中,我选择了'TipMainViewController'。

  3. 将新的UIView拖到新的xib空白画布上。在新的UIView属性检查器中,将“Size”属性设置为“Retina 4 Full Screen”

  4. 选择现有'Classic'3.5“xib中的所有内容 - 例如:所有控件,按钮,选择器,标签等。复制它们并将它们粘贴到新的iPhone 5 xib中。调整大小/移动等。他们优化iPhone的4“显示器。

  5. 与创建原始xib时所做的所有与文件所有者的连接。

  6. 最后,在'single'ViewController的'viewDidLoad'方法中,插入以下逻辑(当然使用你的nib / xib名称):

    - (void)loadView
    {
        [super viewDidLoad];
        if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
        {
            CGSize result = [[UIScreen mainScreen] bounds].size;
            if(result.height == 480)
            {
              // iPhone Classic
              [[NSBundle mainBundle] loadNibNamed:@"TipMainViewController" owner:self options:nil];
            }
            if(result.height == 568)
            {
              // iPhone 5
              [[NSBundle mainBundle] loadNibNamed:@"TipMainViewController-5" owner:self options:nil];
            }
        }
    }
    

答案 1 :(得分:7)

以下是视频控制器的一个简单的工作代码示例,演示如何在iPhone 5上加载myXib-5.xib,在iPhone 5之前加载iPhone / iPod上的myXib.xib

- (void)loadView
{
    if([[UIScreen mainScreen] bounds].size.height == 568)
    {
        // iPhone 5
        self.view = [[NSBundle mainBundle] loadNibNamed:@"myXib-5" owner:self options:nil][0];
    }
    else
    {
        self.view = [[NSBundle mainBundle] loadNibNamed:@"myXib" owner:self options:nil][0];
    }
}

它假设您只针对iPhone而不是iPad,以保持简单。

XIB的文件所有者的类属性也应该设置为包含loadView的视图控制器。

答案 2 :(得分:6)

答案中的代码很有帮助,但我需要一些更适合通用应用程序(iphone / ipad)的东西。

如果其他人需要同样的东西,这里有一些东西可以让你开始。

假设您使用ios的nib / xib命名标准为具有相同名称的xib的视图控制器构建了一个通用应用程序:

在不提供名称时自动加载xibs的两个内置默认值传递给initWithNibName:

  • ExampleViewController.xib [iphone默认为视网膜3.5全屏显示经典布局iphone 4 / 4s等时为空]
  • ExampleViewController~ipad.xib [当nib名为空时,ipad / ipad mini默认]

现在说你需要使用Retina 4全屏选项为IB中的iphone 5/5定制xib,即你不希望任何568h设备显示3.5 xib。

以下是使用类别方法的自定义命名约定:

  • ExampleViewController-568h.xib [当Retina 4全屏(568h)的笔尖名称为空时,iphone非默认/自定义命名约定)

使用类别来帮助为控制器设置正确的xib,而不是覆盖内置的命名默认值。

https://gist.github.com/scottvrosenthal/4945884

ExampleViewController.m

#import "UIViewController+AppCategories.h"

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    nibNameOrNil = [UIViewController nibNamedForDevice:@"ExampleViewController"];

    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {

       // Do any additional customization 

    }

    return self;
}

的UIViewController + AppCategories.h

#import <UIKit/UIKit.h>

@interface UIViewController (AppCategories)

   + (NSString*)nibNamedForDevice:(NSString*)name;

@end

的UIViewController + AppCategories.m

// ExampleViewController.xib [iphone default when nib named empty for Retina 3.5 Full Screen]
// ExampleViewController-568h.xib [iphone custom naming convention when nib named empty for Retina 4 Full Screen (568h)]
// ExampleViewController~ipad.xib [ipad/ipad mini default when nib named empty]

#import "UIViewController+AppCategories.h"

@implementation UIViewController (AppCategories)

+ (NSString*)nibNamedForDevice:(NSString*)name
{

    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
    {
        if ([UIScreen mainScreen].bounds.size.height == 568)
        {
            //Check if there's a path extension or not
            if (name.pathExtension.length) {
                name = [name stringByReplacingOccurrencesOfString: [NSString stringWithFormat:@".%@", name.pathExtension] withString: [NSString stringWithFormat:@"-568h.%@", name.pathExtension ]
                ];

            } else {
                name = [name stringByAppendingString:@"-568h"];
            }

            // if 568h nib is found
            NSString *nibExists = [[NSBundle mainBundle] pathForResource:name ofType:@"nib"];
            if (nibExists) {
                return name;
           }

        }
    }

    // just default to ios universal app naming convention for xibs
    return Nil;
}

@end