在通用应用程序中实例化设备特定视图控制器的正确模式是什么?
我是 Objective-C 的新手,所以请耐心等待。我从 Xcode4 中的通用应用程序模板开始并构建了我的应用程序。模板有一个我试图坚持的约定。对于每个视图控制器,每种设备类型都有一个主文件和一个子类。例如:
Project/
ExampleViewController.(h|m)
- iPhone/
- ExampleViewController_iPhone.(h|m|xib)
- iPad/
- ExampleViewController_iPad.(h|m|xib)
在大多数情况下,这非常方便。大多数逻辑都在超类中,子类负责任何设备特定的实现。
这是我不明白的部分。有时,我的代码在每个子类中执行相同的操作,只是因为我需要为每个设备加载不同的 xib。例如:
ExampleViewController_iPhone
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Content *selectedContent = (Content *)[[self fetchedResultsController] objectAtIndexPath:indexPath];
ContentDetailViewController_iPhone *detailViewController = [[ContentDetailViewController_iPhone alloc] init];
detailViewController.content = selectedContent;
detailViewController.managedObjectContext = self.managedObjectContext;
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
}
ExampleViewController_iPad
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Content *selectedContent = (Content *)[[self fetchedResultsController] objectAtIndexPath:indexPath];
ContentDetailViewController_iPad *detailViewController = [[ContentDetailViewController_iPad alloc] init];
detailViewController.content = selectedContent;
detailViewController.managedObjectContext = self.managedObjectContext;
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
}
...请注意,在第二个实例中,唯一不同的是它加载了视图控制器的 _iPad
版本。这是必要的,因为 iPad
和 iPhone
视图控制器附加到单独的、设备特定的笔尖。
这样做的“正确”模式是什么?
更新
我找到了这个答案 关于使用设备修饰符加载单独的 xib,这似乎可以在我不需要一个设备的特定子类的情况下有所帮助,但如果我需要实例化视图控制器的特定 _iPhone
或 _iPad
实例以实现设备特定功能。
I'm new to objective-C so, bear with me. I started with the Universal App template in Xcode4 and built my application. There is a convention that the template starts you off with that I tried to stick with. For each View Controller, there's a main file and a subclass for each device type. For example:
Project/
ExampleViewController.(h|m)
- iPhone/
- ExampleViewController_iPhone.(h|m|xib)
- iPad/
- ExampleViewController_iPad.(h|m|xib)
For the most part, this is pretty convenient. Most of the logic goes in the superclass and the subclasses take care of any device specific implementation.
Here's the part I don't get. Sometimes I have code that does the same thing in each subclass simply because I need to load a different xib for each device. For example:
ExampleViewController_iPhone
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Content *selectedContent = (Content *)[[self fetchedResultsController] objectAtIndexPath:indexPath];
ContentDetailViewController_iPhone *detailViewController = [[ContentDetailViewController_iPhone alloc] init];
detailViewController.content = selectedContent;
detailViewController.managedObjectContext = self.managedObjectContext;
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
}
ExampleViewController_iPad
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Content *selectedContent = (Content *)[[self fetchedResultsController] objectAtIndexPath:indexPath];
ContentDetailViewController_iPad *detailViewController = [[ContentDetailViewController_iPad alloc] init];
detailViewController.content = selectedContent;
detailViewController.managedObjectContext = self.managedObjectContext;
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
}
... notice that in the second instance the only thing different is that it's loading the _iPad
version of the View Controller. This is necessary because the iPad
and iPhone
view controllers are attached to separate, device specifc nibs.
What's the "correct" pattern for doing this?
UPDATE
I found this answer about loading separate xibs using device modifiers which seems like it could help in the case where I don't need a specific subclass for one device, but it still won't help if I need to instantiate a specific _iPhone
or _iPad
instance of a view controller for device specific functionality.
有两种简单的方法可以解决您的问题。当放入您的超类中时,两者都会起作用。
第一种方法仅有效,因为您有两个不同的类,并且创建哪个类取决于所使用的设备。如果您不使用不同的类,它就不起作用,因为没有特定于设备的代码。它涉及询问对象的类来决定它是哪个类。由于对象的类将是特定于设备的类,因此即使超类要求,您也可以检查创建了哪个类并采取相应的操作。
第二种方法适用于程序中的任何位置。 Apple 在 iOS 3.2 中向 UIDevice 类添加了一个称为“用户界面习惯用法”的属性。目前有两个可能的值:
UIUserInterfaceIdiomPad
和UIUserInterfaceIdiomPhone
。由于这些在 3.2 之前的版本中不存在,Apple 还添加了一个宏,如果版本低于 3.2,则返回 UIUserInterfaceIdiomPhone;如果版本大于 3.2,则从 UIDevice 对象获取实际值或等于3.2。There are two simple ways to solve your problem. Both will work when placed in your superclass.
The first method only works because you have two different classes, and which one is created depends on the device being used. It does not work if you don't use different classes because there is no device-specific code. It involves asking the object for its class to decide which it is. Since the object's class will be the device-specific class, even when asked for by the superclass, you can check to see which class was created and act accordingly.
The second method will work in any location in your program. Apple added a property to the UIDevice class in iOS 3.2 called the "user interface idiom". There are currently two possible values:
UIUserInterfaceIdiomPad
andUIUserInterfaceIdiomPhone
. Since these don't exist in versions prior to 3.2, Apple also added a macro which will returnUIUserInterfaceIdiomPhone
if the version is less than 3.2, and get the actual value from the UIDevice object if it is greater than or equal to 3.2.