1

我正在使用 Xcode 4.2 并正在编写一个通用应用程序。我在开始新项目时选择了 SingleView 应用程序模板。XCode 添加了 ViewController1.h、ViewController1.m、ViewController1_iphone.xib 和 ViewController1_iPad.xib。我需要添加更多 UI 并单击 File...New...New File 并选择 UIViewController 子类模板并看到两个复选框(针对 iPad,使用 Xib 作为用户界面)。

我应该怎么做才能同时支持 iPad 和 iPhone,同时拥有共享相同代码的通用 .h 和 .m 文件。我是否需要通过在视图控制器中执行此操作来添加代码以检查它是 iPad 还是 iPhone?

if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { 
} else {
}

另外,我看到人们在谈论~iPad 和~iPhone。这是怎么回事?

如果我理解正确,由于屏幕尺寸不同,我是否必须为 iPad 和 iPhone 分别设计 UI?

我在这里完全糊涂了。

请帮忙。

4

5 回答 5

6

您可以添加两个笔尖(一个用于 ipad,一个用于 iphone),或者您可以添加一个可以为任一接口正确缩放的笔尖。通常,如果您制作的视图将覆盖整个或大部分屏幕,您会添加两个笔尖,如果您正在制作一些可能会在 iphone 上全屏但显示在ipad 上的弹出窗口。

波浪号后缀在Resource Programming Guide中的“iOS 支持设备特定资源”标题下进行了~ipad描述。请注意,后缀完全是小写,而不是您在问题中所写的驼峰式。这很重要,因为 iOS 使用区分大小写的文件系统。~iphone

当您使用or之NSBundle类的消息获取资源的路径时,iOS 将首先查找后缀为or的资源文件,具体取决于当前设备。例如,假设您这样做:-[NSBundle pathForResource:ofType:]-[NSBundle URLForResource:withExtension:]~ipad~iphone

NSString *path = [[NSBundle mainBundle] pathForResource:@"setup" ofType:@"plist"];
  • 如果您在 iPhone 类型的设备(包括 iPod touch)或 iPhone 模式下的模拟器上运行它,iOS 将首先在您的应用程序包中查找名为setup~iphone.plist. 如果找到这样的文件,它将返回该文件的路径。如果它没有找到该文件,它将改为返回setup.plist.

  • 如果您在 iPad 类型的设备上或在 iPad 模式下的模拟器上执行此操作,iOS 将首先在您的应用程序包中查找名为setup~ipad.plist. 如果找到这样的文件,它将返回该文件的路径。如果它没有找到该文件,它将改为返回setup.plist.

从包中获取资源的所有其他 API 都构建在NSBundle. 这意味着如果您使用+[UIImage imageNamed:],它将自动使用特定于设备的图像,如果您的捆绑包中有一个。如果你使用-[NSBundle loadNibNamed:owner:options:],它会自动加载一个特定于设备的 nib ( .xib) 文件,如果你的包中有一个。

如果您使用后缀,这会简化您的代码。如果您创建MyViewController~ipad.xiband MyViewController~iphone.xib,您的应用将自动为当前设备加载正确的。您不必检查用户界面习语;NSBundle为您检查。(您也可以使用名称MyViewController~ipad.xibandMyViewController.xib并获得相同的效果。)

现在,您可能已经注意到,当您创建“通用”项目时,Xcode 将您的项目文件命名为ViewController1_iPhone.xiband ViewController1_iPad.xib,它使用波浪线后缀,并且它包含查看用户界面习语并相应地选择文件名的代码。为什么通用项目模板会这样做?我不知道,但这很愚蠢。我建议您修复文件名以使用波浪号后缀并删除检查用户界面习语的代码。

于 2012-12-22T22:11:25.277 回答
1

我建议将您的 .xib 文件移动到 Storyboards,一个用于 iPhone,一个用于 iPad。他们为开发带来了很多乐趣,并且易于学习。

然后,将您的自定义类分配给您的视图控制器并将您的 UI 元素链接到您的代码。如果您对两个故事板都这样做,那么它们可以通过引用一个通用的 .h/.m 文件来共享相同的代码。

在项目设置中,一旦应用程序配置为通用开发,您就可以将适当的故事板分配给 iPhone/iPad 部署信息。

于 2012-12-22T22:06:46.567 回答
1

这或多或少取决于您选择如何实现事物和构建事物,但我倾向于使用以下想法:

  • 忽略“Target for iPad”和“With Xib”选项(除非不使用情节提要。见后文)
  • 创建一个包含所有共享代码的父视图控制器。EG MainViewController
  • 为 iPad 和 iPhone 创建 2 个子类。EG MainViewController_iPhone 和 MainViewController_iPad (您可以使用您提到的 MainViewController~iPhone。这里只是命名偏好问题)
  • 您希望在 iPhone 和 iPad 之间共享的任何代码,粘贴在 MainViewController 父类中,以及任何特定于每个设备的代码都放在适当的子类中

一般来说,如果你是在 iPhone 或 iPad 上运行,你真的不需要测试。这并不是说这是错误的,你不应该这样做,但是通过像这样分离类,你真的不需要这样做。但是我喜欢做的是在我处理设备可以处理的方向时检查我正在运行的设备,并将其放入共享的父视图控制器中。

至于您的 UI,您有 3 个选项。- 使用故事板(我推荐这个) - 使用单独的 XIB 文件 - 手动编码所有内容

根据您现在对 iOS 的了解程度,手动编写所有内容可能会更有效率,但很可能会花费您更长的时间。使用界面构建器既好又简单,尽管您仍然需要在代码中进行任何自定义,但这很好。

我建议使用情节提要,这样您就不会拥有大量不同的 XIB 文件。它还简化了 iPhone 和 iPad 之间的拆分,因为您的界面只需 2 个文件。一个将拥有 iPhone 的所有屏幕,一个将拥有 iPad 的所有屏幕。iOS 将在启动时自动加载正确的故事板,因此您无需执行任何操作。然后,要获取视图控制器和视图,您可以执行以下操作:

MainViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"MainViewControllerIdentifier"];

请注意,标识符是在情节提要中指定的。

希望这会有所帮助,但如果您有更多问题,请立即开除 :)

于 2012-12-22T22:11:23.547 回答
1

这是你想要的:

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) 
{
    storyboard = [UIStoryboard storyboardWithName:@"ViewController1_iphone" bundle:nil];
}
else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) 
{
storyboard = [UIStoryboard storyboardWithName:@"ViewController1_ipad" bundle:nil];
}
于 2012-12-23T05:11:50.363 回答
0

如果您将 nib 文件命名为MyNib.xibMyNib~ipad.xib,则将自动加载所需的 nib,具体取决于您的应用程序运行的设备。然而,并不总是需要创建不同的笔尖。如果您不需要太多自定义,并且可以使用 autoresizingMasks 解决,或者您正在以编程方式设置一些框架,则只需一个笔尖即可解决。如果您检查“针对 ipad”部分,您在 nib 中的视图会更大,并且分组表看起来有点不同,但我不知道结果有什么其他差异。

希望这可以帮助!

于 2012-12-22T22:12:35.687 回答