在视图控制器中动态加载 iPhone/iPad 的 nib

Posted

技术标签:

【中文标题】在视图控制器中动态加载 iPhone/iPad 的 nib【英文标题】:Dynamically load nib for iPhone/iPad within view controller 【发布时间】:2011-03-04 09:31:17 【问题描述】:

我已经使用 XCode 中的向导将 iPhone 应用程序转换为通用应用程序。

它构建得很好,但在某些地方显然看起来有点垃圾:)

我需要根据正在使用的设备加载笔尖。我不希望使用initWithNib 创建我的视图控制器,因为我已经有代码来创建带有一些数据(initWithMyLovelyData)的控制器,这与 nib 加载没有任何关系。

我知道要找出您使用的设备UI_USER_INTERFACE_IDIOM(),所以我尝试在实际视图控制器本身中覆盖initWithNibName,假设它们以某种方式在内部被调用。但它不起作用,因为我想我不确定语法。

我试过了

if(ipad..) self = [super initWithNibName:@"MyIpadNib" bundle:nibBundleOrNil];

这不起作用:/

编辑 - 我知道我已经对此进行了大量编辑,在进行更多研究后使我的问题更加具体 - 道歉!

【问题讨论】:

【参考方案1】:

编辑:@Adam 下面的答案是正确答案。

要确定要加载哪个 nib,请执行以下操作,并废弃您的 initWithMyLovelyData 方法并使用属性来设置数据。您应该能够轻松地将所有初始化代码移动到属性设置器方法中。

MyViewController *viewController;

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) 
    viewController = [[MyViewController alloc] initWithNibName:@"ipadNIB" bundle:nil];
 else 
    viewController = [[MyViewController alloc] initWithNibName:@"iphoneNIB" bundle:nil];


viewController.myLovelyData = someData;

【讨论】:

抱歉挖掘旧(呃)帖子,但是:这对我不起作用。有什么想法吗? @Linuxmint 你有什么问题? ***.com/questions/5306346/… FWIW,@adam 的答案是正确的,而且比这要好得多。 由于 nib 名称只是两个字符串之一,其余的 VC 分配/初始化是相同的,您可以通过只调用一次 alloc/init VC 来缩短代码,使用一个 NSString 变量,设置为一个 nib 名称或另一个。【参考方案2】:

我只是将这两个方法放在一个名为 IPadHelper 的类中,并使用 addIPadSuffixWhenOnIPad 方法根据平台有条件地在两个 nib 之间进行选择

+ (BOOL)isIPad
    if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iPhoneOS_3_2)
        if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
            return YES;
        
    
    return NO;


+ (NSString *)addIPadSuffixWhenOnIPad:(NSString *)resourceName
    if([IPadHelper isIPad])
        return [resourceName stringByAppendingString:@"-iPad"];
    
    else 
        return resourceName;
       

第一种方法的更多解释见这里 http://cocoawithlove.com/2010/07/tips-tricks-for-conditional-ios3-ios32.html...

【讨论】:

编译器说这是错误的,因为Class方法应该返回对象(id)。因此,如果认为将其添加到 C 文件中会更好。【参考方案3】:

你也可以吃蛋糕。只需添加一个包装 initWithNibName:bundle: 的方法并添加您的 myLovelyData 参数:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil  myLovelyData:(id)data

    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) 
    
        // Custom initialization using myLovelyData
        //
    
    return self;

【讨论】:

【参考方案4】:

我认为创建 C 文件会更好。 文件助手.h

#import <Foundation/Foundation.h>
BOOL isIPad();
NSString *addIPadSuffixWhenOnIPad(NSString *resourceName);

FileHelper.m

#import "FileHelper.h"
BOOL isIPad() 
    if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iPhoneOS_3_2) 
        if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) 
            return YES;
        
    
    return NO;


NSString *addIPadSuffixWhenOnIPad(NSString *resourceName) 
    if(isIPad()) 
        return [resourceName stringByAppendingString:@"-iPad"];
    
    else 
        return resourceName;
       

【讨论】:

【参考方案5】:

实际上,Apple 会自动执行所有这些操作,只需命名您的 NIB 文件即可:

MyViewController~iphone.xib // iPhone
MyViewController~ipad.xib // iPad

并用最少的代码加载您的视图控制器:

[[MyViewController alloc] initWithNibName:nil bundle:nil]; // Apple will take care of everything

【讨论】:

如果你使用这个语句:[MyViewController alloc] init];相反,在上面的示例中,它是否在做完全相同的事情?还是它在做一些稍微不同的事情? 我希望“init”什么都不做。如果你想让它加载一个 NIB,你需要调用 initWithNib - 或者手动从包中加载一个 NIB [[MyViewController alloc] init] 与 [[MyViewController alloc] initWithNibName:nil nibBundle:nil] 完全相同,在 UIViewController.h 文件中提到:“如果你继承 UIViewController,你必须调用此方法的超级实现,即使您没有使用 NIB。(为方便起见,默认的 init 方法会为您执行此操作,并为此方法的两个参数指定 nil。)" 这是在哪里记录的? UIViewController 中“nibName”的文档指定了在没有提供时如何解析 nib 名称,但似乎没有提及这种方法。 只想补充一点,描述“iOS 支持设备特定资源”的文档部分可以在这里找到:developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/…

以上是关于在视图控制器中动态加载 iPhone/iPad 的 nib的主要内容,如果未能解决你的问题,请参考以下文章

iPhone / iPad 表格视图仅重新加载一行而不是整个表格

是否有用于在表格视图控制器上编辑字段的 iPhone/iPad 库?

在加载 tableview 之前检测 iPhone 方向

如何在 iPhone / iPad 的应用程序中正确使用保留和释放

iOS 单元测试通用应用程序

iPhone/iPad 通用应用程序中 UIPopoverController 的“未找到符号”错误