要让Homepwner的UINavigationController对象真正发挥作用,还要将另一个视图控制器压入UINavigationController对象的栈。选择File菜单中的New菜单项,然后选择File…选中窗口左侧iOS部分的Cocoa Touch,然后选中窗口右侧的Objective-C class,最后单击Next按钮。在新出现的面板中,在Class文本框中输入BNRDetailViewController,在Subclass of下拉菜单中选择UIViewController,勾选选择框With XIB for user interface,单击Next按钮(见图10-7)。Xcode会提示保存文件,单击Save按钮。
图10-7 创建UIViewController子类及相应的XIB文件
在BNRDetailViewController.m中删除@implementation指令和@end指令间的所有代码,修改后的文件内容如下:
#import “BNRDetailViewController.h”
@interface BNRDetailViewController ()
@end
@implementation BNRDetailViewController
@end
下面要为Homepwner添加这些功能:当用户点击UITableView对象中的某个表格行时,Homepwner要显示一个新的屏幕。针对选中的BNRItem对象的每一个属性,这个新的屏幕要显示一个可以编辑的文本框。负责显示BNRItem对象信息的视图应该交由BNRDetail- ViewController控制。
为了显示BNRItem对象的四个属性,需要在BNRDetailViewController中为每一个属性创建一个视图并声明相应的插座变量。下面来添加这些插座变量并在XIB文件中创建相应的关联。
本章之前的例子在创建关联时,需要执行独立三步:①在头文件中声明插座变量。②在XIB文件中设置界面。③在XIB文件中创建关联。Xcode提供了一种快捷途径,可以一次完成这三步。
首先,在项目导航面板中选中BNRDetailViewController.xib。然后,在项目导航面板中按住Option并单击BNRDetailViewController.m,Xcode会在辅助编辑器(assistant editor)中显示该文件,并且之前打开的BNRDetailViewController.xib仍然可见。(找到位于工作空间顶部的Editor控件,单击中间的按钮可以打开/关闭辅助编辑器。显示辅助编辑器的快捷键是Command-Option-回车,返回标准编辑器的快捷键是Command-回车。)
接下来要打开对象库面板,以便将要使用的子视图加入顶层视图。找到位于工作空间右上角的View控件,单击右边的按钮可以打开工具区域(也可以使用快捷键Command-Option-0)。
这时的Xcode窗口会被各种面板占据,下面要暂时腾出一点空间。首先单击View控件左侧的按钮(快捷键是Command-0),隐藏导航面板。然后单击位于编辑区域左下角的切换按钮,将dock由大纲视图切换为图标视图。调整布局后的工作空间如图10-8所示。
图10-8 调整布局后的工作空间
将四个UILabel对象和三个UITextField对象拖曳至画布区域中的顶层视图,然后根据图10-9进行设置。
图10-9 设置后的BNRDetailViewController.xib
请注意,不要将这些子视图放置在view的最顶端。在视图控制器中,view会衬于UINavigationBar的下方,导致UINavigationBar会遮挡view最顶端的内容(对于UITabBar也是同样的情况,因此也不要将子视图放置在view的最底端)。为了方便开发者设置用户界面,Interface Builder为最顶层视图提供了Simulated Metrics,用来预览用户界面的各种外观设置效果,例如顶部带有导航栏或底部带有标签栏的效果。此外,Simulated Metrics中还包括大小、方向、状态栏等设置选项,请读者自行尝试调整这些选项。
首先选中最顶层视图,然后打开属性检视面板,面板顶部显示了Simulated Metrics的一组设置选项,请读者将Top Bar设置为Translucent Navigation Bar(见图10-10)。
图10-10 Simulated Metrics
接下来将三个UITextField对象和位于底部的UILabel对象关联至BNRDetailView- Controller的相应插座变量。在BNRDetailViewController.xib中按住Control,将位于Name标签右侧的UITextField对象拖曳至BNRDetailViewController.m的类扩展中,如图10-11所示。
图10-11 从XIB拖曳至源代码
拖曳至类扩展中后松开鼠标按键,Xcode会弹出设置窗口。在Name文本框中输入nameField,选择Storage下拉菜单中的Weak,单击Connect按钮(见图10-12)。
图10-12 自动生成插座变量并创建关联
上述拖曳操作会为BNRDetailViewController创建一个带IBOutlet前缀的属性,类型为UITextField,名称为nameField。因为nameField属性指向的不是XIB文件中的顶层对象,所以要将引用类型设置为Weak。
上述拖曳操作还会将XIB文件的File/'s Owner的插座变量nameField关联至相应的UITextField对象。要验证上述关联是否存在,可以按住Control并单击File/'s Owner,Xcode会显示关联面板并列出File/'s Owner的所有关联。将光标悬停在面板的nameField关联上,Xcode会高亮显示位于该关联另一端的UITextField对象。通过上述快捷途径,只需一步就能完成插座变量的创建和关联。
重复上述步骤,创建其他三个插座变量,对象名称如图10-13所示。
图10-13 关联图
创建完所有的关联后,BNRDetailViewController.h的代码如下:
#import “BNRDetailViewController.h”
@interface BNRDetailViewController ()
@property (weak, nonatomic) IBOutlet UITextField *nameField;
@property (weak, nonatomic) IBOutlet UITextField *serialNumberField;
@property (weak, nonatomic) IBOutlet UITextField *valueField;
@property (weak, nonatomic) IBOutlet UILabel *dateLabel;
@end
@implementation BNRDetailViewController
@end
如果完成后的BNRDetailViewController.h和本书列出的代码不同,那么很有可能是因为没有正确地创建关联,可以通过以下三步进行修正:首先,重复之前介绍过的拖曳过程,再次创建关联,直到类扩展中的代码和上面列出的代码相同。然后,删除之前由Xcode创建的错误代码(例如方法声明和实例变量声明)。最后,检查XIB文件是否包含错误的关联。打开BNRDetailViewController.xib,按住Control并单击File/'s Owner,Xcode会显示关联面板。如果某个关联有问题,Xcode会在该关联的最右端显示一个感叹号图标。找出有问题的关联,然后通过关联左边的x按钮来删除已经建立的关联。
设置XIB文件时,要确保其中的关联都是正确的,这点非常重要。产生错误关联的常见原因为:读者修改了某个插座变量的变量名,但是没有更新XIB文件中的相应关联;或者读者彻底删除了某个插座变量,但是没有删除XIB文件中的相应关联。无论导致错误关联的原因是什么,当应用载入包含错误关联的XIB文件时,都有可能崩溃。
下面要在BNRDetailViewController.xib中创建剩余的关联。针对XIB文件中的每一个UITextField对象,将其delegate属性关联至File/'s Owner(按住Control,从UITextField对象拖曳至File/'s Owner,然后选择弹出菜单中的delegate)。
Homepwner项目已经初具规模,包含了较多的源代码文件,读者可能经常要在编辑器区域中切换显示这些文件。使用Xcode的标签(tab)功能,可以快速地在多个常用文件之间进行切换。双击项目导航面板中的某个文件,Xcode会在一个新的标签中打开该文件。此外,也可以使用快捷键Command-T来打开一个空白标签。使用快捷键Command-Shift-}可以选中下一个标签,使用快捷键Command-Shift-{可以选中上一个标签。打开Xcode的Preferences(偏好设置)窗口,选择Key Bindings标签,可以看到用于管理项目的其他快捷键。