11 UINavigationController

620 views

Published on

使用 iOS 导航控制器

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
620
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
9
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

11 UINavigationController

  1. 1. UINavigationController范圣刚,princetoad@gmail.com, www.tfan.org
  2. 2. • 前⾯面我们看到了 UITabBarController 能够允许⽤用户访问不 同的 screen,标签栏控件适⽤用于⼏几个 screen 之间互不依 赖的情况• 如果我们想让⽤用户在⼀一些相关联的 screen 之间移动,我 们就可以使⽤用 UINavigationController• ⽐比如 iOS 的 “设置”应⽤用有多个相关的 screen:⼀一系列的 设置和针对每个设置的详细⻚页⾯面,对于每个详细项还有 ⼀一个选项⻚页⾯面,这种类型的界⾯面称作:drill-down interface• 这⼀一个主题我们就使⽤用 UINavigationController 给 Homepwner 添加⼀一个 drill-down interface, 让⽤用户能够查 看和编辑⼀一个 BNRItem 的详细信息
  3. 3. 增加了 UINavigationController 的 Homepwner
  4. 4. UINavigationController
  5. 5. • 当应⽤用程序呈现多屏信息时, UINavigationController 维护了⼀一个这些屏幕的堆 栈(stack)。• 每⼀一个 screen 是 UIViewController 的 view,这个 stack 就是 view controller 的数组。• 当⼀一个 UIViewController 位于 stack 的顶部时,它 的 view 就可⻅见。
  6. 6. • 在初始化⼀一个 UINavigationController 的实例时, 我们给它⼀一个 UIViewController。这个 UIViewController 是 navigation controller 的 root view controller。• 这个 root view controller 总是在堆栈的底部。应⽤用 程序运⾏行时,可以往堆栈中压⼊入更多的 view controller.
  7. 7. • UITabBarController 是在初始化的时候就拿到了它 所有的 view controller,⽽而对于 navigation viewcontroller ,只有它的 root view controller 是保 证⼀一直在堆栈中的• 当 UIViewController 被压⼊入 stack 时,它的 view 是 从右边滑⼊入屏幕;当堆栈弹出的时候,顶层的 view controller 被移出堆栈,它的 view 是从左边 滑⼊入屏幕的
  8. 8. 堆栈• 这是⼀一个带有两个 view controller 的 navigation controller:⼀一个 root view controller,⼀一个是在它之上 的其他 view controller,可⻅见的是上⾯面的 view controller
  9. 9. viewControllers 和 topViewController• 和 UITabBarController 类似, UINavigationController 有⼀一个 viewControllers 数 组。它的 root view controller 是数组中的第⼀一个对 象。当更多的 view controller 被压⼊入堆栈时,他们 被添加到了这个数组的结尾。这样数组中的最后 ⼀一个 view controller 就在堆栈的顶部• UINavigationController 的 topViewController 属性 保持了⼀一个到堆栈顶部的指针
  10. 10. UINavigationController 的 view• UINavigationController 是 UIViewController 的⼦子 类,所以它有⼀一个⾃自⼰己的 view 。它的 view 总是拥 有两个 subview: • ⼀一个是 UINavigationBar • 以及 topViewController 的 view• 也可以把 navigation controller 设成 window 的 rootViewController 来把它的 view 作为 window 的 subview
  11. 11. UINavigationController 的 view
  12. 12. 升级 Homepwner 应⽤用• 这⼀一节我们增加⼀一个 UINavigationController 到 Homepwner 应⽤用并把 ItemsViewController 作为 UINavigationController 的 rootViewController• 然后我们创建另外⼀一个可以压⼊入到 UINavigationController 堆栈的 UIViewController 的 ⼦子类
  13. 13. 升级 Homepwner 应⽤用• 当⽤用户选择其中⼀一⾏行时,新的 UIViewController 的 view 将会滑⼊入屏幕。这个 view controller 将会允 许⽤用户查看和编辑选中的 BNRItem 的属性• 下⼀一⻚页是更新后的 Homepwner 应⽤用的对象⽰示意图
  14. 14. 对象⽰示意图
  15. 15. 增加 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;}
  16. 16. 空的导航栏• 构建并运⾏行我们会发现界⾯面顶部多了⼀一个空⽩白的navigationbar,同时ItemsViewController 的view 被⾃自动调整⼤大⼩小以适应屏幕
  17. 17. 再加⼀一个 UIViewController
  18. 18. • 添加完了 UINavigationController 之后,我们来添 加⽤用来压⼊入 navigation controller 堆栈的另外⼀一个 UIViewController• 创建⼀一个新的 UIViewController ⼦子类,命名为: DetailViewController, 勾选上“With XIB for user interface”
  19. 19. • 在 Homepwner 中,我们希望⽤用户能够轻击⼀一个 item,然后跳到另外⼀一个屏幕.• 在这个新的屏幕上有能够编辑那个 BNRItem 每⼀一 个属性的⽂文本字段。• 这个 view 将会被 DetailViewController 的实例控制
  20. 20. 更简便建⽴立连接的⽅方式• detail view 需要 4 个 subview - 每个针对⼀一个 BNRItem 实例的实例变量• 因为我们需要在运⾏行时访问这些 subview, DetailViewController 需要这些 subviews 的 outlets。这样我们需要添加四个新的 outlets 到 DetailViewController• 可以使⽤用⼀一种稍微简化的⽅方式合并”声明 outlets, 再建⽴立连接的⽅方式”
  21. 21. 配置 DetailViewController XIB
  22. 22. Control-drag UITextField 到DetailViewController.h 实例变量区域
  23. 23. 在弹出窗⼝口输⼊入变量名
  24. 24. 设置完的 DetailViewController.h#import <UIKit/UIKit.h>@interface DetailViewController : UIViewController{ __weak IBOutlet UITextField *nameField; __weak IBOutlet UITextField *serialNumberField; __weak IBOutlet UILabel *dateLabel; __weak IBOutlet UITextField *valueField;} • 注意 XIB ⽂文件不要有坏连接,否则在 XIB ⽂文件被加 载时,应⽤用会崩溃。 • 另外针对 XIB ⽂文件中的每个 UITextField,连接 delegate 属性到 File’s Owner(从 UITextField Control-drag 到 File’s Owner, 然后从列表中选择 delegate)
  25. 25. 使⽤用 NavigationController 导航
  26. 26. • 现在我们已经有了 ⼀一个 navigation controller,以 及两个 view controller 的⼦子类 ( ItemViewController 和 DetailViewController), 下⾯面要把它们连起来⼯工作• 我们要让⽤用户点击 ItemViewController 的 table view 的⼀一⾏行,然后 DetailViewController 的 view 就 可以滑动到屏幕,并且显⽰示选中的 BNRItem 实例 的属性
  27. 27. 压⼊入视图控制器• ⾸首先我们需要创建⼀一个 DetailViewController 的实 例,那么这个对象应该在哪⾥里被创建呢?• 前⾯面的⼏几节我们都是在 application:didFinishLaunchingWithOptions: ⽅方法 中实例化我么需要的所有的 controller
  28. 28. • 例如在tab bar controller ⼀一节,我们创建了两个 view controller,然后⻢马上把它们加到了 tab bar controller 的 viewControllers 数组• 在使⽤用 navigation controller 时,我们不能简单的 把所有可能⽤用到的 view controller 都存到 stack 中
  29. 29. • navigation controller 的数组是动态的,我们开始 于⼀一个 root view controller,然后根据⽤用户的需要 添加 view controller。• 这样navigation controller 之外的⼀一些对象就需要 创建 DetailViewController 的实例,并且负责把它 加⼊入到堆栈中
  30. 30. • 这个对象必须满⾜足两个要求:• 它需要知道什么时候把 DetailViewController 压⼊入堆栈• 它需要⼀一个指向 navigation controller 的指针来给 navigation controller 发送⼀一个名为: pushViewController:animated: 的消息
  31. 31. • ItemsViewController 这两个条件都满⾜足:• 第⼀一,它知道table view 中的⾏行什么时候被轻击,作 为 table view 的 delegate,当这个事件发⽣生时,它会 收到 tableView:didSelectRowAtIndexPath: 消息• 第⼆二,在 navigation controller 堆栈中的 view controller 能够通过给它⾃自⼰己发送 navigationController 消息得到⼀一个指向这个 navigation controller 的指针• 作为 root view controller,ItemsViewController 总是 位于 navigation controller 堆栈中,因此也总是可以 拿到这个指针
  32. 32. navigationController 属性
  33. 33. tableView:didSelectRowAtIndexPath:• 这样就由 ItemsViewController 负责⽣生成 DetailViewController 的实例,并把它加⼊入到堆栈• ⾸首先在 ItemsViewController.h 中导⼊入 DetailViewController 的头⽂文件• 当⼀一⾏行被轻击时,它的 delegate 被发送 tableView:didSelectRowAtIndexPath: 消息,这个消 息包含选中⾏行的 index path• 我们在 ItemsViewController.m 中实现这个⽅方法来 ⽣生成 DetailViewController 然后把它压⼊入 navigation controller 的堆栈
  34. 34. 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 = [[DetailViewControlleralloc] init]; // 压⼊入 navigation controller stack 的顶部 [[self navigationController] pushViewController:detailViewControlleranimated:YES];}
  35. 35. 栈内 view controller 的⽣生命周期• 因为 UINavigationController 的堆栈是⼀一个数组, 它将会拥有所有添加到它⾥里⾯面的 view controller 的 所有权。• 这样在 tableView:didSelectRowAtIndexPath: 结束 之后(⽅方法对它的持有消失), DetailViewController 只会被 UINavigationController 所拥有。• 当堆栈弹出时,DetailViewController 被销毁;当 下⼀一次⼀一⾏行被轻击时,⼀一个新的 DetailViewController 的实例被⽣生成
  36. 36. push view controller 的⼀一般模式• 让⼀一个 view controller 压⼊入新的 view controller 是 ⼀一种常⻅见的模式。• ⼀一般是由 root view controller 创建下⼀一个 view controller,然后这个 view controller 在这之后再创 建下⼀一个 view controller...
  37. 37. • 我么也可以让 view controller 能够压⼊入不同类型的 view controller。• ⽐比如 Photos 应⽤用,根据选中的媒体类型的不同, 可以往 navigation controller 的堆栈中分别压⼊入 video view controller 或者 image view controller
  38. 38. 在 view controller 之间传送数据
  39. 39. • ⺫⽬目前屏幕上的 UITextField 都是空的。要填充这些 字段,我们需要⼀一种⽅方法来把选中的 BNRItem 从 ItemsViewController 中传到 DetailViewController• 要成功实现此功能,我们需要给 DetailViewController ⼀一个属性来持有 BNRItem。 当⼀一⾏行被轻击时,ItemsViewController 将提供相 应的的 BNRItem 给被压⼊入堆栈的 DetailViewController 的实例。
  40. 40. • 这个 DetailViewController 将把这个 BNRItem 的属 性填充到它的⽂文本字段。• 在 DetailViewController 的 view 上编辑 UITextFields 中的⽂文本将改变 BNRItem 的属性
  41. 41. 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
  42. 42. • 在 DetailViewController.m 中为 item sythesize accessor,并且导⼊入 BNRItem 头⽂文件#import "DetailViewController.h"#import "BNRItem.h"@interface DetailViewController ()@end@implementation DetailViewController@synthesize item;
  43. 43. item 内容的显⽰示 • 当 DetailViewController 的 view 显⽰示在屏幕上时, 它需要设置它的 subview 来显⽰示 item 的属性 • 这样我们可以在 DetailViewController.m 中重写 viewWillAppear: 来给各种 UITextFields 传递 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]]];}
  44. 44. 压⼊入堆栈前给 item 赋值 • 下⾯面我们在 ItemViewController.m 中的 tableView:didSelectRowAtIndexPath: 中增加⼀一段代 码,压⼊入堆栈前把选中的 BNRItem 传给 DetailViewController,这样 DetailViewController 就能在 viewWillAppear: 被调⽤用前拿到它的 item- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ DetailViewController *detailViewController = [[DetailViewControlleralloc] init]; NSArray *items = [[BNRItemStore defaultStore] allItems]; BNRItem *selectedItem = [items objectAtIndex:[indexPath row]]; [detailViewController setItem:selectedItem]; // 压⼊入 navigation controller stack 的顶部 [[self navigationController] pushViewController:detailViewControlleranimated:YES];}
  45. 45. view controller 间传递数据的⽅方法• 在 view controller 之间传递数据:把所有的数据都 放到 root view controller,然后传递这些数据的 ⼀一个⼦子集给下⼀一个 UIViewController,是执⾏行这 类任务⽐比较简洁⽽而且⾼高效的⽅方法
  46. 46. • 构建运⾏行,然后选择 UITableView 中的⼀一⾏行,出现 的视图将包含选中的 BNRItem 的信息。但是现在 我们编辑这些数据的时候,UITableView 并不会反 映出这些修改• 我们需要实现⼀一些代码在 BNRItem 被编辑时来更 新它的属性• 这些代码放到什么地⽅方呢?
  47. 47. 视图的出现和消失• 在 UINavigationController 将要切换 view 时,它会 发出两个消息: • viewWillDisappear: • viewWillAppear:• 将被弹出堆栈的 UIViewController 会被发送 viewWillDisappear: 消息• 将要被置顶到堆栈的 UIViewController 被发送 viewWillAppear: 消息• 我们可以在 DetailViewController 被弹出堆栈时, 把它的 item 的属性设置成 UITextFields 的内容
  48. 48. 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]];}
  49. 49. endEditing:• 注意 endEditing: 的使⽤用。当 endEditing: 消息被发 送给⼀一个 view,如果它或者它的任何 subview 当 前是 first responder,它将放弃它的 first responder 状态,并且键盘将被释放。• 传递给它的参数决定了 first responder 是否应该被 强制解除。有些 first 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]];
  50. 50. viewWillAppear: 和 reloadData: • 现在当⽤用户在 UINavigationBar 上轻击 Back 按钮的 时候,BNRItem 的值将被更新。 • 当 ItemViewController 重新出现在屏幕上时,它将 被发送 viewWillAppear: 消息。抓住这个机会来重 新加载 UITableView 这样⽤用户就可以⽴立即看到这些 变更。在 ItemViewController.m 中重写 viewWillAppear: • 构建并运⾏行,切换和数据变更都⾮非常流畅了- (void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; [[self tableView] reloadData];}
  51. 51. UINavigationBar
  52. 52. • UINavigationBar 应该显⽰示当前在 UINavigationController 堆栈顶部的 UIViewController 的标题• 每个 UIViewController 都有⼀一个 UINavigationItem 类型的 navigationItem 属性。但是不像 UINavigationBar,UINavigationItem 不是 UIView 的⼀一个⼦子类,所以它不能出现在屏幕上。 navigation item 提供了navigation bar 它需要绘制 的内容
  53. 53. • 当⼀一个 UIViewController 到达 UINavigationController 堆栈的顶部时, UINavigationBar 使⽤用 UIViewController 的 navigationItem 来配置它⾃自⼰己。• 如下图所⽰示:
  54. 54. UINavigationItem
  55. 55. UINavigationItem 的 title 字符串• 默认情况下,UINavigationItem 是空的。从最基本 的层⾯面上来讲,⼀一个 UINavigationItem 应该有⼀一 个简单的 title 字符串。• 当 UIViewController 被移到 navigation 堆栈的顶部 并且它的 navigationItem 的 title 属性有⼀一个有效 的字符串,navigation bar 将显⽰示这个字符串。• 如下图所⽰示:
  56. 56. 带 title 的 UINavigationItem
  57. 57. 设置 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。
  58. 58. 实现 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]];}
  59. 59. UINavigationItem 的三个区域• 这时候再构建并运⾏行,⽣生成并点击⼀一⾏行的时候我 们就可以在导航栏上看到选中的 BNRItem 的名称
  60. 60. UINavigationItem 的三个区域• ⼀一个 navigation item 可以持有不仅只是⼀一个 title 字符串,如后⾯面的图所⽰示,每个 UINavigationItem 有三个可⾃自定义的区域: • ⼀一个 leftBarButtonItem • ⼀一个 rightBarButtonItem • 和⼀一个 titleView• 左右导航按钮条⺫⽬目被指向 UIBarButtonItem 的实 例,包含的是针对仅可以在 UINavigationBar 或 UIToolbar 上按显⽰示的⼀一个按钮的信息
  61. 61. 包含更多内容的 UINavigationItem
  62. 62. 容器的概念• 和 UINavigationItem ⼀一样,UIBarButtonItem 也不 是 UIView 的⼀一个⼦子类,也只是提供了⼀一个 UINavigationBar 需要绘制的内容• 可以认为 UINavigationItem 和 UIBarButtonItem 是 字符串,图⽚片以及其他内容的容器。• ⼀一个 UINavigationBar 知道如何在这些容器中进⾏行 查找并绘制它找到的内容
  63. 63. titleView• UINavigationItem 的第三个可绘制的区域是它的 titleView。我们可以使⽤用⼀一个基本字符串作为它的 title 或者把⼀一个 UIView 的⼦子类放到 navigation item 的正中。但是我们不能两个都设置。
  64. 64. • 如果给⼀一个特定的 view controller 设置⼀一个⾃自定义 的view(像按钮,滑块,图⽚片,甚⾄至⼀一个地图) 适合上下⽂文,我们就可以把 navigation item 的 titleView 设成这个⾃自定义的 view。⼀一般情况下使 ⽤用⼀一个 title 字符串就⾜足够了。• 前⼀一个图是就是⼀一个使⽤用⾃自定义视图作为 titleView 的例⼦子
  65. 65. UIBarButtonItem 的 target-action• 我们来给 UINavigationBar 添加⼀一个 UIBarButtonItem。• 我们希望这个 UIBarButtonItem 当 ItemsViewController 在堆栈顶部时出现在导航栏 的右侧。• 轻击它的时候,它将往列表中添加⼀一个新的 BNRItem。
  66. 66. • bar button item 具有⼀一个 target-action 对,作⽤用类 似 UIControl 的 target-action 机制:当被轻击时, 它发送 action 消息到它的 target。• 当我们在⼀一个 XIB ⽂文件中设置 target-action 对时, 通过从按钮 Control-drag 到它的 target,然后从 IBActions 列表中选择⼀一个⽅方法。
  67. 67. 编程设置 target 和 action• 要编程设置 target-action 对,我们把 target 和 action 传递给按钮• 我们在 ItemsViewController.m 中⽣生成⼀一个 UIBarButtonItem 的实例并且把它的 target 和 action 传递给它
  68. 68. 修改 ItemsViewController.m 中的init- (id)init{ self = [super initWithStyle:UITableViewStyleGrouped]; if (self) { UINavigationItem *n = [self navigationItem]; [n setTitle:@"Homepwner"]; // 创建⼀一个会发送 addNewItem: 到ItemsViewController 的导航栏按钮 UIBarButtonItem *bbi = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAddtarget:selfaction:@selector(addNewItem:)]; // 设成右边 [[self navigationItem] setRightBarButtonItem:bbi]; } return self;} • 构建并运⾏行,点击+按钮,表格中将出现⼀一个新⾏行 • 令,还有其他的 initialization 消息可以发送给 UIBarButtonItem 的实例
  69. 69. 加⼀一个左按钮 • 现在我们添加另⼀一个 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:UIBarButtonSystemItemAddtarget:selfaction:@selector(addNewItem:)]; [[self navigationItem] setRightBarButtonItem:bbi]; // 加⼀一个编辑按钮 [[self navigationItem] setLeftBarButtonItem:[self editButtonItem]]; } return self;}
  70. 70. editButtonItem: [[self navigationItem] setLeftBarButtonItem:[self editButtonItem]];• 在 navigation bar 中获得⼀一个编辑按钮只需要⼀一⾏行 代码
  71. 71. • editButtonItem 是从哪⾥里来的呢?• UIViewController 有⼀一个 editButtonItem 属性,⽽而 且当被发送 editButtonItem 时,view controller 就 ⽣生成⼀一个标题为“Edit”的 UIBarButtonItem。• 更给⼒力的是,这个按钮⾃自带⼀一个 target-action 对:当轻击时,它发送 setEditing:animated: 消息 给它的 UIViewController。• 构建并运⾏行确认⼀一下 navigation bar 的效果
  72. 72. 删除 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 中删除
  73. 73. 带导航栏的 Homepwner

×