11 uinavigationcontroller

73
UINavigationController 范圣刚,[email protected] , www.tfan.org

Upload: tom-fan

Post on 28-Jun-2015

380 views

Category:

Technology


0 download

DESCRIPTION

使用 iOS 导航控制器

TRANSCRIPT

Page 2: 11 UINavigationController

•前⾯面我们看到了 UITabBarController 能够允许⽤用户访问不同的 screen,标签栏控件适⽤用于⼏几个 screen 之间互不依赖的情况

•如果我们想让⽤用户在⼀一些相关联的 screen 之间移动,我们就可以使⽤用 UINavigationController

•⽐比如 iOS 的 “设置”应⽤用有多个相关的 screen:⼀一系列的设置和针对每个设置的详细⻚页⾯面,对于每个详细项还有⼀一个选项⻚页⾯面,这种类型的界⾯面称作:drill-down interface

•这⼀一个主题我们就使⽤用 UINavigationController 给 Homepwner 添加⼀一个 drill-down interface, 让⽤用户能够查看和编辑⼀一个 BNRItem 的详细信息

Page 3: 11 UINavigationController

增加了 UINavigationController 的 Homepwner

Page 4: 11 UINavigationController

UINavigationController

Page 5: 11 UINavigationController

•当应⽤用程序呈现多屏信息时,UINavigationController 维护了⼀一个这些屏幕的堆栈(stack)。

•每⼀一个 screen 是 UIViewController 的 view,这个 stack 就是 view controller 的数组。

•当⼀一个 UIViewController 位于 stack 的顶部时,它的 view 就可⻅见。

Page 6: 11 UINavigationController

•在初始化⼀一个 UINavigationController 的实例时,我们给它⼀一个 UIViewController。这个 UIViewController 是 navigation controller 的 root view controller。

•这个 root view controller 总是在堆栈的底部。应⽤用程序运⾏行时,可以往堆栈中压⼊入更多的 view controller.

Page 7: 11 UINavigationController

•UITabBarController 是在初始化的时候就拿到了它所有的 view controller,⽽而对于 navigation viewcontroller ,只有它的 root view controller 是保证⼀一直在堆栈中的

•当 UIViewController 被压⼊入 stack 时,它的 view 是从右边滑⼊入屏幕;当堆栈弹出的时候,顶层的 view controller 被移出堆栈,它的 view 是从左边滑⼊入屏幕的

Page 8: 11 UINavigationController

堆栈

•这是⼀一个带有两个 view controller 的 navigation controller:⼀一个 root view controller,⼀一个是在它之上的其他 view controller,可⻅见的是上⾯面的 view controller

Page 9: 11 UINavigationController

viewControllers 和 topViewController

•和 UITabBarController 类似,UINavigationController 有⼀一个 viewControllers 数组。它的 root view controller 是数组中的第⼀一个对象。当更多的 view controller 被压⼊入堆栈时,他们被添加到了这个数组的结尾。这样数组中的 后⼀一个 view controller 就在堆栈的顶部

•UINavigationController 的 topViewController 属性保持了⼀一个到堆栈顶部的指针

Page 10: 11 UINavigationController

UINavigationController 的 view

•UINavigationController 是 UIViewController 的⼦子类,所以它有⼀一个⾃自⼰己的 view 。它的 view 总是拥有两个 subview:•⼀一个是 UINavigationBar

•以及 topViewController 的 view

•也可以把 navigation controller 设成 window 的 rootViewController 来把它的 view 作为 window 的 subview

Page 11: 11 UINavigationController

UINavigationController 的 view

Page 12: 11 UINavigationController

升级 Homepwner 应⽤用•这⼀一节我们增加⼀一个 UINavigationController 到

Homepwner 应⽤用并把 ItemsViewController 作为 UINavigationController 的 rootViewController

•然后我们创建另外⼀一个可以压⼊入到 UINavigationController 堆栈的 UIViewController 的⼦子类

Page 13: 11 UINavigationController

升级 Homepwner 应⽤用•当⽤用户选择其中⼀一⾏行时,新的 UIViewController 的

view 将会滑⼊入屏幕。这个 view controller 将会允许⽤用户查看和编辑选中的 BNRItem 的属性

•下⼀一⻚页是更新后的 Homepwner 应⽤用的对象⽰示意图

Page 14: 11 UINavigationController

对象⽰示意图

Page 15: 11 UINavigationController

增加 UINavigationController

•修改 HomepwnerAppDelegate.m ⽣生成⼀一个 UINavigationController,给它⼀一个 root view controller,并把它设成 window 的 root view controller

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; ItemsViewController *ivc = [[ItemsViewController alloc] init]; UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:ivc]; // [[self window] setRootViewController:ivc]; [[self window] setRootViewController:navController]; self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; return YES;}

Page 16: 11 UINavigationController

空的导航栏•构建并运⾏行我们会发现界⾯面顶部多了⼀一个空⽩白的navigation bar,同时 ItemsViewController 的 view 被⾃自动调整⼤大⼩小以适应屏幕

Page 17: 11 UINavigationController

再加⼀一个 UIViewController

Page 18: 11 UINavigationController

•添加完了 UINavigationController 之后,我们来添加⽤用来压⼊入 navigation controller 堆栈的另外⼀一个 UIViewController

•创建⼀一个新的 UIViewController ⼦子类,命名为:DetailViewController, 勾选上“With XIB for user interface”

Page 19: 11 UINavigationController

•在 Homepwner 中,我们希望⽤用户能够轻击⼀一个 item,然后跳到另外⼀一个屏幕.

•在这个新的屏幕上有能够编辑那个 BNRItem 每⼀一个属性的⽂文本字段。

•这个 view 将会被 DetailViewController 的实例控制

Page 20: 11 UINavigationController

更简便建⽴立连接的⽅方式• detail view 需要 4 个 subview - 每个针对⼀一个

BNRItem 实例的实例变量

•因为我们需要在运⾏行时访问这些 subview,DetailViewController 需要这些 subviews 的 outlets。这样我们需要添加四个新的 outlets 到 DetailViewController

•可以使⽤用⼀一种稍微简化的⽅方式合并”声明 outlets,再建⽴立连接的⽅方式”

Page 21: 11 UINavigationController

配置 DetailViewController XIB

Page 22: 11 UINavigationController

Control-drag UITextField 到 DetailViewController.h 实例变量区域

Page 23: 11 UINavigationController

在弹出窗⼝口输⼊入变量名

Page 24: 11 UINavigationController

设置完的 DetailViewController.h

•注意 XIB ⽂文件不要有坏连接,否则在 XIB ⽂文件被加载时,应⽤用会崩溃。

•另外针对 XIB ⽂文件中的每个 UITextField,连接 delegate 属性到 File’s Owner(从 UITextField Control-drag 到 File’s Owner, 然后从列表中选择 delegate)

#import <UIKit/UIKit.h>

@interface DetailViewController : UIViewController{ __weak IBOutlet UITextField *nameField; __weak IBOutlet UITextField *serialNumberField;

__weak IBOutlet UILabel *dateLabel; __weak IBOutlet UITextField *valueField;

}

Page 25: 11 UINavigationController

使⽤用 NavigationController 导航

Page 26: 11 UINavigationController

•现在我们已经有了 ⼀一个 navigation controller,以及两个 view controller 的⼦子类( ItemViewController 和 DetailViewController),下⾯面要把它们连起来⼯工作

•我们要让⽤用户点击 ItemViewController 的 table view 的⼀一⾏行,然后 DetailViewController 的 view 就可以滑动到屏幕,并且显⽰示选中的 BNRItem 实例的属性

Page 27: 11 UINavigationController

压⼊入视图控制器•⾸首先我们需要创建⼀一个 DetailViewController 的实例,那么这个对象应该在哪⾥里被创建呢?

•前⾯面的⼏几节我们都是在 application:didFinishLaunchingWithOptions: ⽅方法中实例化我么需要的所有的 controller

Page 28: 11 UINavigationController

•例如在tab bar controller ⼀一节,我们创建了两个 view controller,然后⻢马上把它们加到了 tab bar controller 的 viewControllers 数组

•在使⽤用 navigation controller 时,我们不能简单的把所有可能⽤用到的 view controller 都存到 stack 中

Page 29: 11 UINavigationController

• navigation controller 的数组是动态的,我们开始于⼀一个 root view controller,然后根据⽤用户的需要添加 view controller。

•这样navigation controller 之外的⼀一些对象就需要创建 DetailViewController 的实例,并且负责把它加⼊入到堆栈中

Page 30: 11 UINavigationController

•这个对象必须满⾜足两个要求:•它需要知道什么时候把 DetailViewController 压⼊入堆栈

•它需要⼀一个指向 navigation controller 的指针来给 navigation controller 发送⼀一个名为:pushViewController:animated: 的消息

Page 31: 11 UINavigationController

• ItemsViewController 这两个条件都满⾜足:

•第⼀一,它知道table view 中的⾏行什么时候被轻击,作为 table view 的 delegate,当这个事件发⽣生时,它会收到 tableView:didSelectRowAtIndexPath: 消息

•第⼆二,在 navigation controller 堆栈中的 view controller 能够通过给它⾃自⼰己发送 navigationController 消息得到⼀一个指向这个navigation controller 的指针

•作为 root view controller,ItemsViewController 总是位于 navigation controller 堆栈中,因此也总是可以拿到这个指针

Page 32: 11 UINavigationController

navigationController 属性

Page 33: 11 UINavigationController

tableView:didSelectRowAtIndexPath:

•这样就由 ItemsViewController 负责⽣生成 DetailViewController 的实例,并把它加⼊入到堆栈

•⾸首先在 ItemsViewController.h 中导⼊入 DetailViewController 的头⽂文件

•当⼀一⾏行被轻击时,它的 delegate 被发送 tableView:didSelectRowAtIndexPath: 消息,这个消息包含选中⾏行的 index path

•我们在 ItemsViewController.m 中实现这个⽅方法来⽣生成 DetailViewController 然后把它压⼊入 navigation controller 的堆栈

Page 34: 11 UINavigationController

ItemsViewController 中的 didSelectRowAtIndexPath:

#import "ItemsViewController.h"#import "BNRItemStore.h"#import "BNRItem.h"#import "DetailViewController.h"

@implementation ItemsViewController

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ DetailViewController *detailViewController = [[DetailViewController alloc] init]; // 压⼊入 navigation controller stack 的顶部 [[self navigationController] pushViewController:detailViewController animated:YES];}

Page 35: 11 UINavigationController

栈内 view controller 的⽣生命周期•因为 UINavigationController 的堆栈是⼀一个数组,它将会拥有所有添加到它⾥里⾯面的 view controller 的所有权。

•这样在 tableView:didSelectRowAtIndexPath: 结束之后(⽅方法对它的持有消失),DetailViewController 只会被 UINavigationController 所拥有。

•当堆栈弹出时,DetailViewController 被销毁;当下⼀一次⼀一⾏行被轻击时,⼀一个新的 DetailViewController 的实例被⽣生成

Page 36: 11 UINavigationController

push view controller 的⼀一般模式•让⼀一个 view controller 压⼊入新的 view controller 是⼀一种常⻅见的模式。

•⼀一般是由 root view controller 创建下⼀一个 view controller,然后这个 view controller 在这之后再创建下⼀一个 view controller...

Page 37: 11 UINavigationController

•我么也可以让 view controller 能够压⼊入不同类型的 view controller。

•⽐比如 Photos 应⽤用,根据选中的媒体类型的不同,可以往 navigation controller 的堆栈中分别压⼊入 video view controller 或者 image view controller

Page 38: 11 UINavigationController

在 view controller 之间传送数据

Page 39: 11 UINavigationController

•⺫⽬目前屏幕上的 UITextField 都是空的。要填充这些字段,我们需要⼀一种⽅方法来把选中的 BNRItem 从 ItemsViewController 中传到 DetailViewController

•要成功实现此功能,我们需要给 DetailViewController ⼀一个属性来持有 BNRItem。当⼀一⾏行被轻击时,ItemsViewController 将提供相应的的 BNRItem 给被压⼊入堆栈的 DetailViewController 的实例。

Page 40: 11 UINavigationController

•这个 DetailViewController 将把这个 BNRItem 的属性填充到它的⽂文本字段。

•在 DetailViewController 的 view 上编辑 UITextFields 中的⽂文本将改变 BNRItem 的属性

Page 41: 11 UINavigationController

BNRItem *item;

•在 DetailViewController.h 中我们增加⼀一个这个属性

•同时在⽂文件顶部,前置声明 BNRItem#import <UIKit/UIKit.h>

@class BNRItem;

@interface DetailViewController : UIViewController{ __weak IBOutlet UITextField *nameField; __weak IBOutlet UITextField *serialNumberField;

__weak IBOutlet UILabel *dateLabel; __weak IBOutlet UITextField *valueField;

}

@property (nonatomic, strong) BNRItem *item;

@end

Page 42: 11 UINavigationController

•在 DetailViewController.m 中为 item sythesize accessor,并且导⼊入 BNRItem 头⽂文件

#import "DetailViewController.h"#import "BNRItem.h"

@interface DetailViewController ()

@end

@implementation DetailViewController

@synthesize item;

Page 43: 11 UINavigationController

•当 DetailViewController 的 view 显⽰示在屏幕上时,它需要设置它的 subview 来显⽰示 item 的属性

•这样我们可以在 DetailViewController.m 中重写 viewWillAppear: 来给各种 UITextFields 传递 item 的属性

item 内容的显⽰示

- (void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; [nameField setText:[item itemName]]; [serialNumberField setText:[item serialNumber]]; [valueField setText:[NSString stringWithFormat:@"%d", [item valueInDollars]]]; NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateStyle:NSDateFormatterMediumStyle]; [dateFormatter setTimeStyle:NSDateFormatterNoStyle]; [dateLabel setText:[dateFormatter stringFromDate:[item dateCreated]]];}

Page 44: 11 UINavigationController

压⼊入堆栈前给 item 赋值•下⾯面我们在 ItemViewController.m 中的

tableView:didSelectRowAtIndexPath: 中增加⼀一段代码,压⼊入堆栈前把选中的 BNRItem 传给 DetailViewController,这样 DetailViewController 就能在 viewWillAppear: 被调⽤用前拿到它的 item

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ DetailViewController *detailViewController = [[DetailViewController alloc] init]; NSArray *items = [[BNRItemStore defaultStore] allItems]; BNRItem *selectedItem = [items objectAtIndex:[indexPath row]]; [detailViewController setItem:selectedItem]; // 压⼊入 navigation controller stack 的顶部 [[self navigationController] pushViewController:detailViewController animated:YES];}

Page 45: 11 UINavigationController

view controller 间传递数据的⽅方法•在 view controller 之间传递数据:把所有的数据都放到 root view controller,然后传递这些数据的⼀一个⼦子集给下⼀一个 UIViewController,是执⾏行这类任务⽐比较简洁⽽而且⾼高效的⽅方法

Page 46: 11 UINavigationController

•构建运⾏行,然后选择 UITableView 中的⼀一⾏行,出现的视图将包含选中的 BNRItem 的信息。但是现在我们编辑这些数据的时候,UITableView 并不会反映出这些修改

•我们需要实现⼀一些代码在 BNRItem 被编辑时来更新它的属性

•这些代码放到什么地⽅方呢?

Page 47: 11 UINavigationController

视图的出现和消失•在 UINavigationController 将要切换 view 时,它会发出两个消息:• viewWillDisappear:

• viewWillAppear:

•将被弹出堆栈的 UIViewController 会被发送 viewWillDisappear: 消息

•将要被置顶到堆栈的 UIViewController 被发送 viewWillAppear: 消息

•我们可以在 DetailViewController 被弹出堆栈时,把它的 item 的属性设置成 UITextFields 的内容

Page 48: 11 UINavigationController

viewWillDisappear: 及超类•当实现这些针对 view 的 appearing 和

disappearing 的⽅方法时,⾮非常重要的⼀一点是要调⽤用他们超类的实现 - 这些超类⾥里⾯面也有⼀一些⼯工作要做。我们在 DetailViewController.m 中实现 viewWillDisappear:

- (void)viewWillDisappear:(BOOL)animated{ [super viewWillDisappear:animated]; // clear first responder [[self view] endEditing:YES]; // 保存变更到 item [item setItemName:[nameField text]]; [item setSerialNumber:[serialNumberField text]]; [item setValueInDollars:[[valueField text] intValue]];}

Page 49: 11 UINavigationController

endEditing:

•注意 endEditing: 的使⽤用。当 endEditing: 消息被发送给⼀一个 view,如果它或者它的任何 subview 当前是 !rst responder,它将放弃它的 !rst responder 状态,并且键盘将被释放。

•传递给它的参数决定了 !rst responder 是否应该被强制解除。有些 !rst responder 可能会拒绝放弃,传递 YES 将会忽略这个拒绝。

[super viewWillDisappear:animated]; // clear first responder [[self view] endEditing:YES]; // 保存变更到 item [item setItemName:[nameField text]]; [item setSerialNumber:[serialNumberField text]]; [item setValueInDollars:[[valueField text] intValue]];

Page 50: 11 UINavigationController

viewWillAppear: 和 reloadData:

•现在当⽤用户在 UINavigationBar 上轻击 Back 按钮的时候,BNRItem 的值将被更新。

•当 ItemViewController 重新出现在屏幕上时,它将被发送 viewWillAppear: 消息。抓住这个机会来重新加载 UITableView 这样⽤用户就可以⽴立即看到这些变更。在 ItemViewController.m 中重写 viewWillAppear:

•构建并运⾏行,切换和数据变更都⾮非常流畅了- (void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; [[self tableView] reloadData];}

Page 51: 11 UINavigationController

UINavigationBar

Page 52: 11 UINavigationController

•UINavigationBar 应该显⽰示当前在 UINavigationController 堆栈顶部的 UIViewController 的标题

•每个 UIViewController 都有⼀一个 UINavigationItem 类型的 navigationItem 属性。但是不像 UINavigationBar,UINavigationItem 不是 UIView 的⼀一个⼦子类,所以它不能出现在屏幕上。navigation item 提供了navigation bar 它需要绘制的内容

Page 53: 11 UINavigationController

•当⼀一个 UIViewController 到达 UINavigationController 堆栈的顶部时,UINavigationBar 使⽤用 UIViewController 的 navigationItem 来配置它⾃自⼰己。

•如下图所⽰示:

Page 54: 11 UINavigationController

UINavigationItem

Page 55: 11 UINavigationController

UINavigationItem 的 title 字符串•默认情况下,UINavigationItem 是空的。从 基本的层⾯面上来讲,⼀一个 UINavigationItem 应该有⼀一个简单的 title 字符串。

•当 UIViewController 被移到 navigation 堆栈的顶部并且它的 navigationItem 的 title 属性有⼀一个有效的字符串,navigation bar 将显⽰示这个字符串。

•如下图所⽰示:

Page 56: 11 UINavigationController

带 title 的 UINavigationItem

Page 57: 11 UINavigationController

设置 ItemViewController 的 title

•在 ItemViewController.m 中修改 init 来设置 navigationItem 的 title 以显⽰示 Homepwner

- (id)init{ self = [super initWithStyle:UITableViewStyleGrouped]; if (self) { UINavigationItem *n = [self navigationItem]; [n setTitle:@"Homepwner"]; } return self;}

•构建并运⾏行我们注意到在 navigation bar 上的 Homepwner 字符串。但是点击⼀一⾏行以后 title 不在了,我们需要也给 DetailViewController ⼀一个 title。

Page 58: 11 UINavigationController

实现 setItem: 并设置 title

•我们要把 DetailViewController 的 navigation item 的 title 设置成 BNRItem 显⽰示的名称⼀一致。

•但是我们不能在 DetailViewController 的 init 中设置,因为这时候还不知道它的 item 会是什么

•我们要在 DetailViewController 设置它的 item 属性的时候设置它的 title。在 DetailViewController.m 中实现 setItem: 以替换 item 的synthesized 默认的 setter ⽅方法

- (void)setItem:(BNRItem *)i{ item = i; [[self navigationItem] setTitle:[item itemName]];}

Page 59: 11 UINavigationController

UINavigationItem 的三个区域•这时候再构建并运⾏行,⽣生成并点击⼀一⾏行的时候我们就可以在导航栏上看到选中的 BNRItem 的名称

Page 60: 11 UINavigationController

UINavigationItem 的三个区域•⼀一个 navigation item 可以持有不仅只是⼀一个 title 字符串,如后⾯面的图所⽰示,每个 UINavigationItem 有三个可⾃自定义的区域:•⼀一个 leftBarButtonItem

•⼀一个 rightBarButtonItem

•和⼀一个 titleView

•左右导航按钮条⺫⽬目被指向 UIBarButtonItem 的实例,包含的是针对仅可以在 UINavigationBar 或 UIToolbar 上按显⽰示的⼀一个按钮的信息

Page 61: 11 UINavigationController

包含更多内容的 UINavigationItem

Page 62: 11 UINavigationController

容器的概念•和 UINavigationItem ⼀一样,UIBarButtonItem 也不是 UIView 的⼀一个⼦子类,也只是提供了⼀一个 UINavigationBar 需要绘制的内容

•可以认为 UINavigationItem 和 UIBarButtonItem 是字符串,图⽚片以及其他内容的容器。

•⼀一个 UINavigationBar 知道如何在这些容器中进⾏行查找并绘制它找到的内容

Page 63: 11 UINavigationController

titleView

•UINavigationItem 的第三个可绘制的区域是它的 titleView。我们可以使⽤用⼀一个基本字符串作为它的 title 或者把⼀一个 UIView 的⼦子类放到 navigation item 的正中。但是我们不能两个都设置。

Page 64: 11 UINavigationController

•如果给⼀一个特定的 view controller 设置⼀一个⾃自定义的view(像按钮,滑块,图⽚片,甚⾄至⼀一个地图)适合上下⽂文,我们就可以把 navigation item 的 titleView 设成这个⾃自定义的 view。⼀一般情况下使⽤用⼀一个 title 字符串就⾜足够了。

•前⼀一个图是就是⼀一个使⽤用⾃自定义视图作为 titleView 的例⼦子

Page 65: 11 UINavigationController

UIBarButtonItem 的 target-action

•我们来给 UINavigationBar 添加⼀一个 UIBarButtonItem。

•我们希望这个 UIBarButtonItem 当ItemsViewController 在堆栈顶部时出现在导航栏的右侧。

•轻击它的时候,它将往列表中添加⼀一个新的 BNRItem。

Page 66: 11 UINavigationController

• bar button item 具有⼀一个 target-action 对,作⽤用类似 UIControl 的 target-action 机制:当被轻击时,它发送 action 消息到它的 target。

•当我们在⼀一个 XIB ⽂文件中设置 target-action 对时,通过从按钮 Control-drag 到它的 target,然后从 IBActions 列表中选择⼀一个⽅方法。

Page 67: 11 UINavigationController

编程设置 target 和 action

•要编程设置 target-action 对,我们把 target 和 action 传递给按钮

•我们在 ItemsViewController.m 中⽣生成⼀一个 UIBarButtonItem 的实例并且把它的 target 和 action 传递给它

Page 68: 11 UINavigationController

修改 ItemsViewController.m 中的init

•构建并运⾏行,点击+按钮,表格中将出现⼀一个新⾏行

•令,还有其他的 initialization 消息可以发送给 UIBarButtonItem 的实例

- (id)init{ self = [super initWithStyle:UITableViewStyleGrouped]; if (self) { UINavigationItem *n = [self navigationItem]; [n setTitle:@"Homepwner"]; // 创建⼀一个会发送 addNewItem: 到ItemsViewController 的导航栏按钮 UIBarButtonItem *bbi = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addNewItem:)]; // 设成右边 [[self navigationItem] setRightBarButtonItem:bbi]; } return self;}

Page 69: 11 UINavigationController

加⼀一个左按钮•现在我们添加另⼀一个 UIBarButtonItem 来替换掉表格头部中 Edit 按钮。在 ItemViewController.m 中继续修改 init ⽅方法

- (id)init{ self = [super initWithStyle:UITableViewStyleGrouped]; if (self) { UINavigationItem *n = [self navigationItem]; [n setTitle:@"Homepwner"]; UIBarButtonItem *bbi = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addNewItem:)]; [[self navigationItem] setRightBarButtonItem:bbi]; // 加⼀一个编辑按钮 [[self navigationItem] setLeftBarButtonItem:[self editButtonItem]]; } return self;}

Page 70: 11 UINavigationController

editButtonItem:

•在 navigation bar 中获得⼀一个编辑按钮只需要⼀一⾏行代码

[[self navigationItem] setLeftBarButtonItem:[self editButtonItem]];

Page 71: 11 UINavigationController

• editButtonItem 是从哪⾥里来的呢?

•UIViewController 有⼀一个 editButtonItem 属性,⽽而且当被发送 editButtonItem 时,view controller 就⽣生成⼀一个标题为“Edit”的 UIBarButtonItem。

•更给⼒力的是,这个按钮⾃自带⼀一个 target-action 对:当轻击时,它发送 setEditing:animated: 消息给它的 UIViewController。

•构建并运⾏行确认⼀一下 navigation bar 的效果

Page 72: 11 UINavigationController

删除 header view 相关代码•现在 Homepwner 已经有了⼀一个全功能的导航栏,可以把项⺫⽬目中有关 header view 及其相关的代码都删除掉了• ItemsViewController.m 中的• tableView:viewForHeaderInSection:

• tableView:heightForHeaderInSection:

• headerView:

• toggleEditingMode:

• ItemsViewController.h 中的• IBOutlet UIView *headerView;

• - (UIView *)headerView;

• - (IBAction)toggleEditingMode:

• 还可以把 HeaderView.xib ⽂文件从 project navigator 中删除

Page 73: 11 UINavigationController

带导航栏的 Homepwner