不同设备的不同笔尖

Posted

技术标签:

【中文标题】不同设备的不同笔尖【英文标题】:Different Nibs for different devices 【发布时间】:2011-04-08 00:28:18 【问题描述】:

所以我正在编写一个应用程序,我希望它是通用的。创建项目时,我创建了一个通用应用程序。我已经编写了所有的 iPhone 代码并且有 10 个类。现在我想创建 iPad 版本。与其拥有两组代码基本完全相同的类,我想根据设备类型加载不同的 Nib。

我尝试在应用程序委托中使用 BOOL,但遇到了问题。我尝试在 mainViewController 类(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 中进行设备检查,我根据设备类型返回了一个不同的笔尖。但我只能得到iphone版本或空白笔尖。提前感谢您的帮助。

【问题讨论】:

【参考方案1】:

根据文档(资源编程指南),您可以使用如下命名约定: myNibName~ipad.xib 和 myNibName~iphone.xib 所以每个文件都只能在支持的设备上打开。你甚至不需要设置不同的 appDelegate :)

--- 来自文档 --- 在 ios 4.0 及更高版本中,可以将单个资源文件标记为仅在特定类型的设备上可用。此功能简化了您必须为通用应用程序编写的代码。您可以让捆绑加载例程选择正确的文件,而不是创建单独的代码路径来为 iPhone 加载一个版本的资源文件和为 iPad 加载不同版本的文件。您所要做的就是适当地命名您的资源文件。

要将资源文件与特定设备关联,您可以在其文件名中添加自定义修饰符字符串。包含此修饰符字符串会生成具有以下格式的文件名:

.

字符串代表资源文件的原始名称。它还代表您从代码访问文件时使用的名称。同样,字符串是用于标识文件类型的标准文件扩展名。该字符串是区分大小写的字符串,可以是以下值之一:

~ipad - 资源只能在 iPad 设备上加载。 ~iphone - 资源只能在 iPhone 或 iPod touch 设备上加载。

【讨论】:

“~ipad”和“~iphone”中的小写“p”对我来说感觉不对,但它确实是 Apple 所描述的。文档链接:developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/… 小写“p”非常重要。 ~iPad 可以运行模拟器,但无法在真实设备上加载。某些版本的 XCode 会创建 ~iPad 文件(带有大写的“P”),这会产生误导并且不起作用。 ^^ 感谢 Johan 和 Woj。我自己也很好奇。【参考方案2】:

Apple 现在为您提供了一种默认机制,可在同一项目中将您的代码在 iPhone 和 iPad 之间分离。

在 Xcode 4 中,当您创建新的“基于窗口的应用程序”或“基于视图的应用程序”时,您可以选择“设备系列”。如果您为此选项选择“通用”,Xcode 将创建 3 个应用代理。

首先,一个主应用委托:

YourAppNameAppDelegate : NSObject <UIApplicationDelegate> 

以及作为“YourAppNameAppDelegate”子类的另外两个应用代理(放置在不同的组中):

YourAppNameAppDelegate_iPhone : YourAppNameAppDelegate
YourAppNameAppDelegate_iPad : YourAppNameAppDelegate

当您使用 iPhone 或 iPad 模拟器(或设备)运行应用程序时,应用程序将根据所选设备自动使用 _iPhone 或 _iPad 应用程序委托子类。

如果你在每个子类中重写 application:didFinishLaunchingWithOptions: 方法,你会看到这个工作:

// In YourAppNameAppDelegate_iPhone.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

    NSLog(@"iPhone App Delegate");
    return [super application:application didFinishLaunchingWithOptions:launchOptions];


// In YourAppNameAppDelegate_iPad.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

    NSLog(@"iPad App Delegate");
    return [super application:application didFinishLaunchingWithOptions:launchOptions];

这为您提供了一个起点,您可以根据用户所在的设备更改程序流程。例如,通过实例化主视图控制器的子类之一(如下所述)。

当您向项目中添加新的视图控制器时,您应该通过创建一个通用控制器超类和一个 iPhone/iPad 特定子类来继续这种范例。请注意,通用超类不应该有与之关联的 nib 文件,而子类应该有各自独立的 nib。

这样您就可以在三个类之间拆分代码,在超类中保留与平台无关的东西 - 例如一些属性、方法、IBOutlets 和 IBActions - 并将特定于平台的实现放入任一子类中。

【讨论】:

有什么理由不进行转换?它是免费的.. developer.apple.com/xcode xcode 4 是公开发布还是处于测试阶段?我看到它处于测试阶段,并查看了所有主要变化,只是想我会坚持一些我失败的东西。我不经常查看 dev.apple.com 已公开发布。虽然我弄错了,但如果你是 iOS 开发者计划的一部分,它才是免费的。否则 4.99 美元。 我在 iOS 付费开发者计划中。我想我会得到它【参考方案3】:

我遇到过这个问题,通过自定义UIViewController的initWithNibName:bundle:方法解决了。

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

  // See below for definition of "LWEUniversalAppHelpers fileNamed:"
  NSString *universalNibName = [LWEUniversalAppHelpers fileNamed:nibNameOrNil];
  if ((self = [super initWithNibName:universalNibName bundle:nibBundleOrNil]))
  
    // Custom initialization
  
  return self;

LWEUniversalAppHelpers 是我公司编写的一个帮助类,用于确定设备是否为 iPad。是public on GitHub,但基本概念是使用 Retina 的“@2x”策略,而我们使用“@HD”。

【讨论】:

看起来很酷,但是当 iPad 3 或 4 有 Retina 显示屏然后你被@HD@2x 卡住时会发生什么。那会是一团糟。【参考方案4】:

我想通了:

在Interface Builder中,使用File->Create ipad version

然后保存文件,并将其添加到项目中。然后在分配时,初始化每个viewController,检查是否UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad,否则它是一个iPhone 或iPod Touch。初次保存后我无法对其进行编辑,但它可以工作。

【讨论】:

以上是关于不同设备的不同笔尖的主要内容,如果未能解决你的问题,请参考以下文章

不同笔尖的collectionView单元格宽度不会改变

UITableViewHeaderFooterView 不支持笔尖中的自动布局约束

单个笔尖的多个视图

使用多个笔尖在 UITableViewCell 中动态获取行高

UICollectionViewCell 无法注册笔尖?

带有多个笔尖的 UIScrollView 中未声明的视图