咱們知道 UITabBarController 對象,能夠經過使用該對象,用戶能夠切換不一樣的屏幕。當要切換的各個屏幕之間沒有相互依存關係的時候,該對象能夠很好的完成任務。可是當多個屏幕互有關係的時候,就要使用另外一種控制器 UINavigationController 。 事實上,基本上在全部的 APP 中,必不可少的兩種控制器。git
咱們以 iOS 自帶的 設置 應用爲例,設置應用擁有多個互有關聯的窗口,咱們稱之爲這種界面爲 垂直界面 。github
下面咱們將使用 UINavigationController 對象將 JXHomepwner 對象加入到 垂直界面 。項目地址 數組
當某個應用經過 UINavigationController 對象顯示多個屏幕的信息時,相應的 UINavigationController 對象會以棧的形式保存全部屏幕的信息。這裏的棧是一個數組對象,保存的都是 UIViewController 對象。一個 UIViewController 對象的視圖對應一個屏幕。只用位於棧頂的 UIViewController 對象,其視圖纔是可見的。app
初始化 UINavigationController 對象時,須要傳入一個 UIViewController 對象。這個 UIViewController 對象將成爲 UINavigationController 對象的 根視圖控制器(root view controller),且根視圖控制器將永遠位於棧底。應用能夠在運行時向 UINavigationController 的棧底壓入更多的視圖控制器。ide
將某個視圖控制器壓入 UINavigationController 對象的棧時,新加入的視圖控制器的視圖會從窗口右側推入。出棧時, UINavigationController 對象會移除位於棧頂的視圖控制器,其視圖會向窗口右側推出,而後用戶會看見僅次於棧頂位置的視圖控制器的視圖。atom
相似於 UITabBarController 對象, UINavigationController 對象有一個名爲 viewControllers 的屬性,指向一個負責保存視圖控制器的數組對象。在這個數組對象中,根視圖控制器是第一個對象。當應用將某個視圖控制器壓入棧後,UINavigationController 對象會將新加入的對象加在 viewControllers 數組的末尾。所以,該數組中的最後一個視圖控制器會位於棧的頂部。UINavigationController 對象的 topViewController 屬性是一個指針,指向當前位於棧頂的視圖控制器。spa
UINavigationController 是 UIViewController 的子類,因此 UINavigationController 對象也有本身的視圖。該對象的視圖有兩個子視圖:一個是 UINavigationBar 對象,另外一個是 topViewController 的視圖。和其餘視圖控制器同樣,能夠將 UINavigationController 對象設置爲 UIWindow 對象的 rootViewController ,從而將該對象的視圖做爲子視圖加入窗口。3d
首先爲項目添加一個 UINavigationController 對象。指針
#import "AppDelegate.h" #import "JXItemsViewController.h" @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; // 添加初始化代碼 // 建立 JXItemsViewController 對象 JXItemsViewController * itemsViewController = [[JXItemsViewController alloc] init]; // 將 JXItemsViewController 的標示圖加入窗口 self.window.rootViewController = itemsViewController; // 將 UINavigationController 對象設置爲 UIWindow 對象的根視圖控制器。 // 這樣就能夠將 UINavigationController 對象的視圖添加到屏幕中 UINavigationController * navController = [[UINavigationController alloc] initWithRootViewController:itemsViewController]; self.window.rootViewController = navController; self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; return YES; }
構建並運行,除了屏幕頂部新出現的 UINavigationController 對象,真個應用看上去跟以前沒有任何差異。JXItemsViewController 對象的視圖大小會發生變化以適應帶 UINavigationBar 對象的屏幕。這項工做是由 UINavigationController 完成的。code
要讓 JXHomepwner 的 UINavigationController 對象真正的發揮做用,還要將另外一個視圖控制器壓入 UINavigationController 對象的棧中。建立新的控制器,同時勾選 XIB。
下面咱們須要爲應用添加功能:當用戶點擊 UITableView 對象中的某個表格行時,應用須要顯示一個新的屏幕。針對選中的 JXItem 對象的每個屬性,這個心得屏幕都要顯示一個能夠編輯的文本框。負責顯示 JXItem 對象信息的視圖應該由 JXDetailViewController 控制。
爲了顯示 JXItem 對象的四個屬性,須要在 JXDetialViewController 中爲每個屬性建立一個視圖並聲明相應的插座變量。
建立關聯時,須要執行獨立三步:1.在頭文件中聲明插座變量。2.在 XIB 文件中設置界面。3.在 XIB 文件中建立關聯。
設置視圖的時候請注意不要將這些子視圖放置在 view 最頂端。在視圖控制器中,view 會襯於 UINavigationBar 的下方,致使 UINavigationBar 會遮擋 view 最頂端的內容(對於 UITabBar 也是一樣的狀況,所以也不要將子視圖放置在 view 的最低端)。關聯後的代碼。
#import "JXDetailViewController.h" @interface JXDetailViewController () @property (weak, nonatomic) IBOutlet UITextField *nameField; @property (weak, nonatomic) IBOutlet UITextField *seriaNumberField; @property (weak, nonatomic) IBOutlet UITextField *valueField; @property (weak, nonatomic) IBOutlet UILabel *dateLabel; @end @implementation JXDetailViewController - (void)viewDidLoad { [super viewDidLoad]; } @end
設置 XIB 文件時,要確保其中的關聯都是正確的,這點很是重要。產生錯誤關聯常見的緣由爲:咱們修改了某個插座變量的便令名,可是沒有更新 XIB 文件中的相應關聯;或者咱們完全刪除了某個插座變量,可是沒有刪除 XIB 文件中的相應關聯。
下面要在 xib 中建立針對每個 UITextField 對象,將其 delegate 屬性關聯至 File's Owner (按住 Control , 從 UITextField 對象拖拽置 File's Owner ,而後選擇彈出菜單中的 delegate)。
前面咱們已經加入了一個 UINavigationController 對象。下面咱們就須要將咱們所需的對象組合在一塊兒。
將視圖控制器壓入棧
若是想要完成目標,就須要建立 JXDetailViewController 對象。可是咱們須要知道如何,什麼時候,在哪裏建立這個控制器。因此這個 UINavigationController 對象的 viewControllers 數組是動態的:一開始只有一個根視圖,應用須要根據狀況來推出新的視圖控制器。所以,應用須要某個對象來負責建立 JXDetailViewController 對象,並將新的建立的對象壓入 UINavigationController 對象的棧。
這個負責建立 JXDetailViewController 對象的對象須要知足兩個條件:首先,由於該對象是 UITableView 對象的委託,因此當用戶點擊 UITableView 對象的某個表格行時,JXItemsViewController 對象就會收到
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
其次,凡是加入了某個 UINavigationController 對象的棧的視圖控制器,均可以向本身發送 navigationController 消息,以獲得指向該對象的指針。由於應用會將 JXItemsViewController 對象設置爲 UINavigationController 對象的根視圖控制器,因此 JXItemsViewController 對象會一直停留在 UINavigationController 對象的棧中,從而使JXItemsViewController 對象總能獲得指向響應 UINavigationController 的指針。
所以,應該由 JXItemsViewController 對象負責建立 JXDetailViewController 對象並將其加入到 UINavigationController 對象的棧中。
#import "JXItemsViewController.h" #import "JXItem.h" #import "JXItemStore.h" #import "JXDetailViewController.h" @interface JXItemsViewController () /** 頭部視圖 */ @property (nonatomic,weak) UIView * headerView; /** 編輯按鈕 */ @property (nonatomic,strong) UIButton * editButton; /** 增長按鈕 */ @property (nonatomic,strong) UIButton * addButton; @end @implementation JXItemsViewController - (instancetype)init { // 調用父類的指定初始化方法 self = [super initWithStyle:UITableViewStylePlain]; if (self) { for (NSInteger i=0; i<5; i++) { [[JXItemStore sharedStore] createItem]; } } return self; } - (instancetype)initWithStyle:(UITableViewStyle)style { return [self init]; } - (void)viewDidLoad { [super viewDidLoad]; // 向控制器註冊 [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"UITableViewCell"]; // 加載頭視圖 [self headerView]; } #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [[[JXItemStore sharedStore] allItem] count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // 建立 UITableViewCell 對象,風格使用默認風格 UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell" forIndexPath:indexPath]; // 獲取 allItem 的第 n 個 JXItem 對象 // 而後將該 JXItem 對象的描述信息賦值給 UITableViewCell 對象的 textLabel // 這裏的 n 是該 UITableViewCell 對象所對應的表格索引 NSArray * items = [[JXItemStore sharedStore] allItem]; JXItem * item = items[indexPath.row]; cell.textLabel.text = [item description]; return cell; } /** * 刪除行 * * @param tableView 對象 * @param editingStyle 操做 * @param indexPath 操做的行數 */ - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { // 若是tableView請求的是刪除對象 if (editingStyle == UITableViewCellEditingStyleDelete) { // 取出須要刪除的對象 NSArray * items = [[JXItemStore sharedStore] allItem]; JXItem * item = items[indexPath.row]; // 刪除對象 [[JXItemStore sharedStore] removeItem:item]; // 刷新表格 [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; } } /** * 移動行 * * @param tableView 對象 * @param sourceIndexPath 須要移動的行 * @param destinationIndexPath 目標行 */ - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath { [[JXItemStore sharedStore] moveItemAtIndex:sourceIndexPath.row toIndex:destinationIndexPath.row]; } #pragma mark - UITalbeViewDelegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { JXDetailViewController * detailController = [[JXDetailViewController alloc] init]; // 將新建立的控制器壓入到導航控制器對象棧中 [self.navigationController pushViewController:detailController animated:YES]; } #pragma mark - 懶加載 - (UIView *)headerView{ if (_headerView == nil) { UIView * headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 50)]; // 設置頭部視圖 self.tableView.tableHeaderView = headerView; headerView.backgroundColor = [UIColor cyanColor]; [headerView addSubview:self.editButton]; [headerView addSubview:self.addButton]; _headerView = headerView; } return _headerView; } - (UIButton *)editButton{ if (_editButton == nil) { _editButton = [UIButton buttonWithType:UIButtonTypeCustom]; _editButton.frame = CGRectMake(0, 0, self.view.bounds.size.width / 2, 50); [_editButton setTitle:@"Edit" forState:UIControlStateNormal]; _editButton.backgroundColor = [UIColor greenColor]; [_editButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [_editButton addTarget:self action:@selector(editClick:) forControlEvents:UIControlEventTouchDown]; } return _editButton; } - (UIButton *)addButton{ if (_addButton == nil) { UIButton * addButton = [UIButton buttonWithType:UIButtonTypeCustom]; addButton.frame = CGRectMake(self.view.bounds.size.width / 2, 0, self.view.bounds.size.width / 2, 50); [addButton setTitle:@"Add" forState:UIControlStateNormal]; addButton.backgroundColor = [UIColor blueColor]; [addButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [addButton addTarget:self action:@selector(addClick:) forControlEvents:UIControlEventTouchDown]; _addButton = addButton; } return _addButton; } #pragma mark - 點擊事件 - (void)editClick:(UIButton *)sender { if (self.isEditing) { // 若是是編輯狀態,取消編輯 // 更改文字 [sender setTitle:@"Edit" forState:UIControlStateNormal]; // 取消編輯 [self setEditing:NO animated:YES]; } else { // 更改文字 [sender setTitle:@"Done" forState:UIControlStateNormal]; // 開始編輯 [self setEditing:YES animated:YES]; } } /** * 添加表格時,必須保證 UITableView 對象當前顯示的行數與數據源的提供的行數相同。 * 因此,在添加以前,必須先建立一個新的 JXItem 對象並加入到 JXItemStore 中 * * @param sender 按鈕 */ - (void)addClick:(UIButton *)sender { // 建立新的 JXItem 對象,並加入到 JXItemStore 中 JXItem * newItem = [[JXItemStore sharedStore] createItem]; // 獲取新的對象在 allItem 數組中的索引 NSInteger lastRow = [[[JXItemStore sharedStore] allItem] indexOfObject:newItem]; NSIndexPath * indexPath = [NSIndexPath indexPathForRow:lastRow inSection:0]; // 將新航插入 UITableView 對象 [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationBottom]; [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO]; } @end
視圖控制器之間的數據傳遞
下面爲push進來的控制器設置顯示內容。
首先爲 JXDetailViewController 添加一個屬性,用來保存指定的 JXItem 對象。當用戶點擊 UITableView 對象中的某個行時,JXItemsViewController 對象應該將選中的 JXItem 對象傳給即將壓入棧的 JXDetailViewController 對象。獲得 JXItem 對象後,JXDetailViewController 對象就能夠針對相應的 JXItem 屬性設置全部的 UITextField 對象。
#import <UIKit/UIKit.h> @class JXItem; @interface JXDetailViewController : UIViewController /** 接收參數 */ @property (nonatomic,strong) JXItem * item; @end
#import "JXDetailViewController.h" #import "JXItem.h" @interface JXDetailViewController () @property (weak, nonatomic) IBOutlet UITextField *nameField; @property (weak, nonatomic) IBOutlet UITextField *seriaNumberField; @property (weak, nonatomic) IBOutlet UITextField *valueField; @property (weak, nonatomic) IBOutlet UILabel *dateLabel; @end @implementation JXDetailViewController - (void)viewDidLoad { [super viewDidLoad]; JXItem * item = self.item; self.nameField.text = item.itemName; self.seriaNumberField.text = item.itemName; self.valueField.text = [NSString stringWithFormat:@"%ld",item.valueInDollars]; // 建立 NSDdateFoemateter 對象,用於將 NSDate 對象轉換成簡單的日期字符串 static NSDateFormatter * dateFormatter = nil; if (!dateFormatter) { dateFormatter = [[NSDateFormatter alloc] init]; dateFormatter.dateStyle = NSDateFormatterMediumStyle; dateFormatter.timeStyle = NSDateFormatterNoStyle; } // 將轉換後獲得的日期字符串設置爲 dateLabel 的標題 self.dateLabel.text = [dateFormatter stringFromDate:item.createDate]; } @end
#import "JXItemsViewController.h" #import "JXItem.h" #import "JXItemStore.h" #import "JXDetailViewController.h" @interface JXItemsViewController () /** 頭部視圖 */ @property (nonatomic,weak) UIView * headerView; /** 編輯按鈕 */ @property (nonatomic,strong) UIButton * editButton; /** 增長按鈕 */ @property (nonatomic,strong) UIButton * addButton; @end @implementation JXItemsViewController - (instancetype)init { // 調用父類的指定初始化方法 self = [super initWithStyle:UITableViewStylePlain]; if (self) { for (NSInteger i=0; i<5; i++) { [[JXItemStore sharedStore] createItem]; } } return self; } - (instancetype)initWithStyle:(UITableViewStyle)style { return [self init]; } - (void)viewDidLoad { [super viewDidLoad]; // 向控制器註冊 [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"UITableViewCell"]; // 加載頭視圖 [self headerView]; } #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [[[JXItemStore sharedStore] allItem] count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // 建立 UITableViewCell 對象,風格使用默認風格 UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell" forIndexPath:indexPath]; // 獲取 allItem 的第 n 個 JXItem 對象 // 而後將該 JXItem 對象的描述信息賦值給 UITableViewCell 對象的 textLabel // 這裏的 n 是該 UITableViewCell 對象所對應的表格索引 NSArray * items = [[JXItemStore sharedStore] allItem]; JXItem * item = items[indexPath.row]; cell.textLabel.text = [item description]; return cell; } /** * 刪除行 * * @param tableView 對象 * @param editingStyle 操做 * @param indexPath 操做的行數 */ - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { // 若是tableView請求的是刪除對象 if (editingStyle == UITableViewCellEditingStyleDelete) { // 取出須要刪除的對象 NSArray * items = [[JXItemStore sharedStore] allItem]; JXItem * item = items[indexPath.row]; // 刪除對象 [[JXItemStore sharedStore] removeItem:item]; // 刷新表格 [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; } } /** * 移動行 * * @param tableView 對象 * @param sourceIndexPath 須要移動的行 * @param destinationIndexPath 目標行 */ - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath { [[JXItemStore sharedStore] moveItemAtIndex:sourceIndexPath.row toIndex:destinationIndexPath.row]; } #pragma mark - UITalbeViewDelegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { JXDetailViewController * detailController = [[JXDetailViewController alloc] init]; NSArray * items = [[JXItemStore sharedStore] allItem]; JXItem * selectedItem = items[indexPath.row]; // 將選中的JXItem 對象賦給 DetailViewController 對象 detailController.item = selectedItem; // 將新建立的控制器壓入到導航控制器對象棧中 [self.navigationController pushViewController:detailController animated:YES]; } #pragma mark - 懶加載 - (UIView *)headerView{ if (_headerView == nil) { UIView * headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 50)]; // 設置頭部視圖 self.tableView.tableHeaderView = headerView; headerView.backgroundColor = [UIColor cyanColor]; [headerView addSubview:self.editButton]; [headerView addSubview:self.addButton]; _headerView = headerView; } return _headerView; } - (UIButton *)editButton{ if (_editButton == nil) { _editButton = [UIButton buttonWithType:UIButtonTypeCustom]; _editButton.frame = CGRectMake(0, 0, self.view.bounds.size.width / 2, 50); [_editButton setTitle:@"Edit" forState:UIControlStateNormal]; _editButton.backgroundColor = [UIColor greenColor]; [_editButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [_editButton addTarget:self action:@selector(editClick:) forControlEvents:UIControlEventTouchDown]; } return _editButton; } - (UIButton *)addButton{ if (_addButton == nil) { UIButton * addButton = [UIButton buttonWithType:UIButtonTypeCustom]; addButton.frame = CGRectMake(self.view.bounds.size.width / 2, 0, self.view.bounds.size.width / 2, 50); [addButton setTitle:@"Add" forState:UIControlStateNormal]; addButton.backgroundColor = [UIColor blueColor]; [addButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [addButton addTarget:self action:@selector(addClick:) forControlEvents:UIControlEventTouchDown]; _addButton = addButton; } return _addButton; } #pragma mark - 點擊事件 - (void)editClick:(UIButton *)sender { if (self.isEditing) { // 若是是編輯狀態,取消編輯 // 更改文字 [sender setTitle:@"Edit" forState:UIControlStateNormal]; // 取消編輯 [self setEditing:NO animated:YES]; } else { // 更改文字 [sender setTitle:@"Done" forState:UIControlStateNormal]; // 開始編輯 [self setEditing:YES animated:YES]; } } /** * 添加表格時,必須保證 UITableView 對象當前顯示的行數與數據源的提供的行數相同。 * 因此,在添加以前,必須先建立一個新的 JXItem 對象並加入到 JXItemStore 中 * * @param sender 按鈕 */ - (void)addClick:(UIButton *)sender { // 建立新的 JXItem 對象,並加入到 JXItemStore 中 JXItem * newItem = [[JXItemStore sharedStore] createItem]; // 獲取新的對象在 allItem 數組中的索引 NSInteger lastRow = [[[JXItemStore sharedStore] allItem] indexOfObject:newItem]; NSIndexPath * indexPath = [NSIndexPath indexPathForRow:lastRow inSection:0]; // 將新航插入 UITableView 對象 [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationBottom]; [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO]; } @end
雖然咱們已經成功的將數據傳入到下一個控制器中,可是當屏幕返回 JXItemsViewController 對象後,UITableView 對象不會根據用戶修改來顯示更新內容。
視圖的顯示和消失
當 UINavigationController 對象切換視圖時,其包含的兩個 UIViewController 對象會分別收到 viewWillDisappear: 消息和 viewWillAppear: 消息。即將出棧的 UIViewController 對象會收到 viewWillDisappear: 消息,即將入棧的 UIViewController 對象會收到 viewWillAppear: 消息。
當某個 JXDetailViewController 對象退出棧時,應該將各個 UITextField 對象的值賦給 JXItem 對象的相應屬性。覆蓋 viewWillDisappear: 和 viewWillAppear: 時,必須先調用其父類實現。
#import "JXDetailViewController.h" #import "JXItem.h" @interface JXDetailViewController () @property (weak, nonatomic) IBOutlet UITextField *nameField; @property (weak, nonatomic) IBOutlet UITextField *seriaNumberField; @property (weak, nonatomic) IBOutlet UITextField *valueField; @property (weak, nonatomic) IBOutlet UILabel *dateLabel; @end @implementation JXDetailViewController - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; // 取消當前的第一響應對象 [self.view endEditing:YES]; // 將修改保存到 JXItem JXItem * item = self.item; item.itemName = self.nameField.text; item.serialnumber = self.seriaNumberField.text; item.valueInDollars = [self.valueField.text integerValue]; } - (void)viewDidLoad { [super viewDidLoad]; JXItem * item = self.item; self.nameField.text = item.itemName; self.seriaNumberField.text = item.itemName; self.valueField.text = [NSString stringWithFormat:@"%ld",item.valueInDollars]; // 建立 NSDdateFoemateter 對象,用於將 NSDate 對象轉換成簡單的日期字符串 static NSDateFormatter * dateFormatter = nil; if (!dateFormatter) { dateFormatter = [[NSDateFormatter alloc] init]; dateFormatter.dateStyle = NSDateFormatterMediumStyle; dateFormatter.timeStyle = NSDateFormatterNoStyle; } // 將轉換後獲得的日期字符串設置爲 dateLabel 的標題 self.dateLabel.text = [dateFormatter stringFromDate:item.createDate]; } @end
當點擊 UINavigationBar 對象上的返回按鈕時,須要進行的操做
#import "JXItemsViewController.h" #import "JXItem.h" #import "JXItemStore.h" #import "JXDetailViewController.h" @interface JXItemsViewController () /** 頭部視圖 */ @property (nonatomic,weak) UIView * headerView; /** 編輯按鈕 */ @property (nonatomic,strong) UIButton * editButton; /** 增長按鈕 */ @property (nonatomic,strong) UIButton * addButton; @end @implementation JXItemsViewController - (instancetype)init { // 調用父類的指定初始化方法 self = [super initWithStyle:UITableViewStylePlain]; if (self) { for (NSInteger i=0; i<5; i++) { [[JXItemStore sharedStore] createItem]; } } return self; } - (instancetype)initWithStyle:(UITableViewStyle)style { return [self init]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self.tableView reloadData]; } - (void)viewDidLoad { [super viewDidLoad]; // 向控制器註冊 [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"UITableViewCell"]; // 加載頭視圖 [self headerView]; } #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [[[JXItemStore sharedStore] allItem] count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // 建立 UITableViewCell 對象,風格使用默認風格 UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell" forIndexPath:indexPath]; // 獲取 allItem 的第 n 個 JXItem 對象 // 而後將該 JXItem 對象的描述信息賦值給 UITableViewCell 對象的 textLabel // 這裏的 n 是該 UITableViewCell 對象所對應的表格索引 NSArray * items = [[JXItemStore sharedStore] allItem]; JXItem * item = items[indexPath.row]; cell.textLabel.text = [item description]; return cell; } /** * 刪除行 * * @param tableView 對象 * @param editingStyle 操做 * @param indexPath 操做的行數 */ - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { // 若是tableView請求的是刪除對象 if (editingStyle == UITableViewCellEditingStyleDelete) { // 取出須要刪除的對象 NSArray * items = [[JXItemStore sharedStore] allItem]; JXItem * item = items[indexPath.row]; // 刪除對象 [[JXItemStore sharedStore] removeItem:item]; // 刷新表格 [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; } } /** * 移動行 * * @param tableView 對象 * @param sourceIndexPath 須要移動的行 * @param destinationIndexPath 目標行 */ - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath { [[JXItemStore sharedStore] moveItemAtIndex:sourceIndexPath.row toIndex:destinationIndexPath.row]; } #pragma mark - UITalbeViewDelegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { JXDetailViewController * detailController = [[JXDetailViewController alloc] init]; NSArray * items = [[JXItemStore sharedStore] allItem]; JXItem * selectedItem = items[indexPath.row]; // 將選中的JXItem 對象賦給 DetailViewController 對象 detailController.item = selectedItem; // 將新建立的控制器壓入到導航控制器對象棧中 [self.navigationController pushViewController:detailController animated:YES]; } #pragma mark - 懶加載 - (UIView *)headerView{ if (_headerView == nil) { UIView * headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 50)]; // 設置頭部視圖 self.tableView.tableHeaderView = headerView; headerView.backgroundColor = [UIColor cyanColor]; [headerView addSubview:self.editButton]; [headerView addSubview:self.addButton]; _headerView = headerView; } return _headerView; } - (UIButton *)editButton{ if (_editButton == nil) { _editButton = [UIButton buttonWithType:UIButtonTypeCustom]; _editButton.frame = CGRectMake(0, 0, self.view.bounds.size.width / 2, 50); [_editButton setTitle:@"Edit" forState:UIControlStateNormal]; _editButton.backgroundColor = [UIColor greenColor]; [_editButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [_editButton addTarget:self action:@selector(editClick:) forControlEvents:UIControlEventTouchDown]; } return _editButton; } - (UIButton *)addButton{ if (_addButton == nil) { UIButton * addButton = [UIButton buttonWithType:UIButtonTypeCustom]; addButton.frame = CGRectMake(self.view.bounds.size.width / 2, 0, self.view.bounds.size.width / 2, 50); [addButton setTitle:@"Add" forState:UIControlStateNormal]; addButton.backgroundColor = [UIColor blueColor]; [addButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [addButton addTarget:self action:@selector(addClick:) forControlEvents:UIControlEventTouchDown]; _addButton = addButton; } return _addButton; } #pragma mark - 點擊事件 - (void)editClick:(UIButton *)sender { if (self.isEditing) { // 若是是編輯狀態,取消編輯 // 更改文字 [sender setTitle:@"Edit" forState:UIControlStateNormal]; // 取消編輯 [self setEditing:NO animated:YES]; } else { // 更改文字 [sender setTitle:@"Done" forState:UIControlStateNormal]; // 開始編輯 [self setEditing:YES animated:YES]; } } /** * 添加表格時,必須保證 UITableView 對象當前顯示的行數與數據源的提供的行數相同。 * 因此,在添加以前,必須先建立一個新的 JXItem 對象並加入到 JXItemStore 中 * * @param sender 按鈕 */ - (void)addClick:(UIButton *)sender { // 建立新的 JXItem 對象,並加入到 JXItemStore 中 JXItem * newItem = [[JXItemStore sharedStore] createItem]; // 獲取新的對象在 allItem 數組中的索引 NSInteger lastRow = [[[JXItemStore sharedStore] allItem] indexOfObject:newItem]; NSIndexPath * indexPath = [NSIndexPath indexPathForRow:lastRow inSection:0]; // 將新航插入 UITableView 對象 [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationBottom]; [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO]; } @end
構建並運行。便可更改信息。
UINavigationBar 目前沒有顯示任何內容,下面咱們設置一些顯示內容。
UIViewController 對象有一個名爲 navigationItem 的屬性,類型爲 UINavigationItem 。和 UINavigationBar 不一樣,UINavigaitonItem 不是 UIView 的子類,不能再屏幕上顯示。UINavigationItem 對象的做用是爲 UINavigationBar 對象提供繪圖所需的內容。當某個 UIViewController 對象成爲 UINavigationController 的棧頂控制器對象時,UINavigationBar 對象就會訪問該 UIViewController 對象的 navigationItem 。
UINavigationItem 對象默認是空,設置方式爲
#import "JXItemsViewController.h" #import "JXItem.h" #import "JXItemStore.h" #import "JXDetailViewController.h" @interface JXItemsViewController () /** 頭部視圖 */ @property (nonatomic,weak) UIView * headerView; /** 編輯按鈕 */ @property (nonatomic,strong) UIButton * editButton; /** 增長按鈕 */ @property (nonatomic,strong) UIButton * addButton; @end @implementation JXItemsViewController - (instancetype)init { // 調用父類的指定初始化方法 self = [super initWithStyle:UITableViewStylePlain]; if (self) { UINavigationItem * navItem = self.navigationItem; navItem.title = @"JXHomepwner"; for (NSInteger i=0; i<5; i++) { [[JXItemStore sharedStore] createItem]; } } return self; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self.tableView reloadData]; } - (void)viewDidLoad { [super viewDidLoad]; // 向控制器註冊 [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"UITableViewCell"]; // 加載頭視圖 [self headerView]; } #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [[[JXItemStore sharedStore] allItem] count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // 建立 UITableViewCell 對象,風格使用默認風格 UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell" forIndexPath:indexPath]; // 獲取 allItem 的第 n 個 JXItem 對象 // 而後將該 JXItem 對象的描述信息賦值給 UITableViewCell 對象的 textLabel // 這裏的 n 是該 UITableViewCell 對象所對應的表格索引 NSArray * items = [[JXItemStore sharedStore] allItem]; JXItem * item = items[indexPath.row]; cell.textLabel.text = [item description]; return cell; } /** * 刪除行 * * @param tableView 對象 * @param editingStyle 操做 * @param indexPath 操做的行數 */ - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { // 若是tableView請求的是刪除對象 if (editingStyle == UITableViewCellEditingStyleDelete) { // 取出須要刪除的對象 NSArray * items = [[JXItemStore sharedStore] allItem]; JXItem * item = items[indexPath.row]; // 刪除對象 [[JXItemStore sharedStore] removeItem:item]; // 刷新表格 [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; } } /** * 移動行 * * @param tableView 對象 * @param sourceIndexPath 須要移動的行 * @param destinationIndexPath 目標行 */ - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath { [[JXItemStore sharedStore] moveItemAtIndex:sourceIndexPath.row toIndex:destinationIndexPath.row]; } #pragma mark - UITalbeViewDelegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { JXDetailViewController * detailController = [[JXDetailViewController alloc] init]; NSArray * items = [[JXItemStore sharedStore] allItem]; JXItem * selectedItem = items[indexPath.row]; // 將選中的JXItem 對象賦給 DetailViewController 對象 detailController.item = selectedItem; // 將新建立的控制器壓入到導航控制器對象棧中 [self.navigationController pushViewController:detailController animated:YES]; } #pragma mark - 懶加載 - (UIView *)headerView{ if (_headerView == nil) { UIView * headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 50)]; // 設置頭部視圖 self.tableView.tableHeaderView = headerView; headerView.backgroundColor = [UIColor cyanColor]; [headerView addSubview:self.editButton]; [headerView addSubview:self.addButton]; _headerView = headerView; } return _headerView; } - (UIButton *)editButton{ if (_editButton == nil) { _editButton = [UIButton buttonWithType:UIButtonTypeCustom]; _editButton.frame = CGRectMake(0, 0, self.view.bounds.size.width / 2, 50); [_editButton setTitle:@"Edit" forState:UIControlStateNormal]; _editButton.backgroundColor = [UIColor greenColor]; [_editButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [_editButton addTarget:self action:@selector(editClick:) forControlEvents:UIControlEventTouchDown]; } return _editButton; } - (UIButton *)addButton{ if (_addButton == nil) { UIButton * addButton = [UIButton buttonWithType:UIButtonTypeCustom]; addButton.frame = CGRectMake(self.view.bounds.size.width / 2, 0, self.view.bounds.size.width / 2, 50); [addButton setTitle:@"Add" forState:UIControlStateNormal]; addButton.backgroundColor = [UIColor blueColor]; [addButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [addButton addTarget:self action:@selector(addClick:) forControlEvents:UIControlEventTouchDown]; _addButton = addButton; } return _addButton; } #pragma mark - 點擊事件 - (void)editClick:(UIButton *)sender { if (self.isEditing) { // 若是是編輯狀態,取消編輯 // 更改文字 [sender setTitle:@"Edit" forState:UIControlStateNormal]; // 取消編輯 [self setEditing:NO animated:YES]; } else { // 更改文字 [sender setTitle:@"Done" forState:UIControlStateNormal]; // 開始編輯 [self setEditing:YES animated:YES]; } } /** * 添加表格時,必須保證 UITableView 對象當前顯示的行數與數據源的提供的行數相同。 * 因此,在添加以前,必須先建立一個新的 JXItem 對象並加入到 JXItemStore 中 * * @param sender 按鈕 */ - (void)addClick:(UIButton *)sender { // 建立新的 JXItem 對象,並加入到 JXItemStore 中 JXItem * newItem = [[JXItemStore sharedStore] createItem]; // 獲取新的對象在 allItem 數組中的索引 NSInteger lastRow = [[[JXItemStore sharedStore] allItem] indexOfObject:newItem]; NSIndexPath * indexPath = [NSIndexPath indexPathForRow:lastRow inSection:0]; // 將新航插入 UITableView 對象 [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationBottom]; [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO]; } @end
構建並運行;UINavigationBar 對象會顯示咱們設置的標題。添加一個新的控制器(選中表格行),UINavigationBar 對象的標題會消失,因此下面咱們要繼續設置。
#import "JXDetailViewController.h" #import "JXItem.h" @interface JXDetailViewController () @property (weak, nonatomic) IBOutlet UITextField *nameField; @property (weak, nonatomic) IBOutlet UITextField *seriaNumberField; @property (weak, nonatomic) IBOutlet UITextField *valueField; @property (weak, nonatomic) IBOutlet UILabel *dateLabel; @end @implementation JXDetailViewController - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; // 取消當前的第一響應對象 [self.view endEditing:YES]; // 將修改保存到 JXItem JXItem * item = self.item; item.itemName = self.nameField.text; item.serialnumber = self.seriaNumberField.text; item.valueInDollars = [self.valueField.text integerValue]; } - (void)viewDidLoad { [super viewDidLoad]; JXItem * item = self.item; self.nameField.text = item.itemName; self.seriaNumberField.text = item.itemName; self.valueField.text = [NSString stringWithFormat:@"%ld",item.valueInDollars]; // 建立 NSDdateFoemateter 對象,用於將 NSDate 對象轉換成簡單的日期字符串 static NSDateFormatter * dateFormatter = nil; if (!dateFormatter) { dateFormatter = [[NSDateFormatter alloc] init]; dateFormatter.dateStyle = NSDateFormatterMediumStyle; dateFormatter.timeStyle = NSDateFormatterNoStyle; } // 將轉換後獲得的日期字符串設置爲 dateLabel 的標題 self.dateLabel.text = [dateFormatter stringFromDate:item.createDate]; } - (void)setItem:(JXItem *)item { _item = item; self.navigationItem.title = _item.itemName; } @end
UINavigationItem 對象除了能夠設置標題字符串外,還能夠設置若干其餘的界面屬性。包括 : leftBarButtonItem 、 rightBarButtonItem 和 titleView 。其中 leftBarButtonItem 和 rightBarButtonItem 都是指向 UIBarButtonItem 對象的指針,該對象包含顯示某種特殊按鈕所須要的信息,這種按鈕只能在 UINavigationBar 對象或 UIToolbar 對象中使用。
相似於 UINavigationItem ,UIBarButtonItem 也不是 UIView 的子類。UINavigationItem 對象封裝了一些設置信息,以便於 UINavigationBar 在運行時能夠正確顯示該對象。一樣,UIBarButtonItem 對象封裝了關於如何在 UINavigationBar 顯示單個按鈕的信息,UINavigationBar 對象會根據 UIBarButtonItem 對象中的信息顯示相應的按鈕。(UIToolbar 與 UINavigationBar 同樣,也是經過 UIBarButtonItem 對象來顯示按鈕的。)
除了 leftBarButtonItem 和 rightBarButtonItem ,UINavigationItem 對象的第三個界面屬性 titleView 。UINavigationBar 對象包含兩種標題顯示模式。第一種是顯示一個簡單的字符串。第二種模式是顯示一個視圖。兩種模式不能共存。若是須要在 UINavigationBar 對象正中顯示一個複雜界面,就能夠先建立擁有自定義視圖(例如 UIButton 對象、UISlider 對象、UIImageView 對象等)的視圖控制器,而後爲該對象的 titleView 賦值,並指向這個自定義視圖。
下面讓 UINavigationBar 對象顯示一個按鈕:當 JXItemsViewController 對象位於棧頂時,在 UINavigationBar 對象的右端顯示一個按鈕。當用戶點擊這個按鈕時,爲UITableView 對象增長一個新的表格。
爲了能在用戶點擊 UINavigationBar 對象中的按鈕時觸發指定的方法,必須爲相應的 UIBarButtonItem 對象設置目標-動做對。
#import "JXItemsViewController.h" #import "JXItem.h" #import "JXItemStore.h" #import "JXDetailViewController.h" @interface JXItemsViewController () /** 頭部視圖 */ @property (nonatomic,weak) UIView * headerView; /** 編輯按鈕 */ @property (nonatomic,strong) UIButton * editButton; /** 增長按鈕 */ @property (nonatomic,strong) UIButton * addButton; @end @implementation JXItemsViewController - (instancetype)init { // 調用父類的指定初始化方法 self = [super initWithStyle:UITableViewStylePlain]; if (self) { UINavigationItem * navItem = self.navigationItem; navItem.title = @"JXHomepwner"; // 建立新的 UIBarButtonItem 對象 // 將其目標對象設置爲當前對象,將其多作方法設置爲指定方法 UIBarButtonItem * bdi = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addClick:)]; // 爲 UINavigationItem 對象的 rightBarButtonItem 屬性賦值 // 指向新建立的 UIBarButtonItem 對象 navItem.rightBarButtonItem = bdi; for (NSInteger i=0; i<5; i++) { [[JXItemStore sharedStore] createItem]; } } return self; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self.tableView reloadData]; } - (void)viewDidLoad { [super viewDidLoad]; // 向控制器註冊 [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"UITableViewCell"]; // 加載頭視圖 [self headerView]; } #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [[[JXItemStore sharedStore] allItem] count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // 建立 UITableViewCell 對象,風格使用默認風格 UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell" forIndexPath:indexPath]; // 獲取 allItem 的第 n 個 JXItem 對象 // 而後將該 JXItem 對象的描述信息賦值給 UITableViewCell 對象的 textLabel // 這裏的 n 是該 UITableViewCell 對象所對應的表格索引 NSArray * items = [[JXItemStore sharedStore] allItem]; JXItem * item = items[indexPath.row]; cell.textLabel.text = [item description]; return cell; } /** * 刪除行 * * @param tableView 對象 * @param editingStyle 操做 * @param indexPath 操做的行數 */ - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { // 若是tableView請求的是刪除對象 if (editingStyle == UITableViewCellEditingStyleDelete) { // 取出須要刪除的對象 NSArray * items = [[JXItemStore sharedStore] allItem]; JXItem * item = items[indexPath.row]; // 刪除對象 [[JXItemStore sharedStore] removeItem:item]; // 刷新表格 [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; } } /** * 移動行 * * @param tableView 對象 * @param sourceIndexPath 須要移動的行 * @param destinationIndexPath 目標行 */ - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath { [[JXItemStore sharedStore] moveItemAtIndex:sourceIndexPath.row toIndex:destinationIndexPath.row]; } #pragma mark - UITalbeViewDelegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { JXDetailViewController * detailController = [[JXDetailViewController alloc] init]; NSArray * items = [[JXItemStore sharedStore] allItem]; JXItem * selectedItem = items[indexPath.row]; // 將選中的JXItem 對象賦給 DetailViewController 對象 detailController.item = selectedItem; // 將新建立的控制器壓入到導航控制器對象棧中 [self.navigationController pushViewController:detailController animated:YES]; } #pragma mark - 懶加載 - (UIView *)headerView{ if (_headerView == nil) { UIView * headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 50)]; // 設置頭部視圖 self.tableView.tableHeaderView = headerView; headerView.backgroundColor = [UIColor cyanColor]; [headerView addSubview:self.editButton]; [headerView addSubview:self.addButton]; _headerView = headerView; } return _headerView; } - (UIButton *)editButton{ if (_editButton == nil) { _editButton = [UIButton buttonWithType:UIButtonTypeCustom]; _editButton.frame = CGRectMake(0, 0, self.view.bounds.size.width / 2, 50); [_editButton setTitle:@"Edit" forState:UIControlStateNormal]; _editButton.backgroundColor = [UIColor greenColor]; [_editButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [_editButton addTarget:self action:@selector(editClick:) forControlEvents:UIControlEventTouchDown]; } return _editButton; } - (UIButton *)addButton{ if (_addButton == nil) { UIButton * addButton = [UIButton buttonWithType:UIButtonTypeCustom]; addButton.frame = CGRectMake(self.view.bounds.size.width / 2, 0, self.view.bounds.size.width / 2, 50); [addButton setTitle:@"Add" forState:UIControlStateNormal]; addButton.backgroundColor = [UIColor blueColor]; [addButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [addButton addTarget:self action:@selector(addClick:) forControlEvents:UIControlEventTouchDown]; _addButton = addButton; } return _addButton; } #pragma mark - 點擊事件 - (void)editClick:(UIButton *)sender { if (self.isEditing) { // 若是是編輯狀態,取消編輯 // 更改文字 [sender setTitle:@"Edit" forState:UIControlStateNormal]; // 取消編輯 [self setEditing:NO animated:YES]; } else { // 更改文字 [sender setTitle:@"Done" forState:UIControlStateNormal]; // 開始編輯 [self setEditing:YES animated:YES]; } } /** * 添加表格時,必須保證 UITableView 對象當前顯示的行數與數據源的提供的行數相同。 * 因此,在添加以前,必須先建立一個新的 JXItem 對象並加入到 JXItemStore 中 * * @param sender 按鈕 */ - (void)addClick:(UIButton *)sender { // 建立新的 JXItem 對象,並加入到 JXItemStore 中 JXItem * newItem = [[JXItemStore sharedStore] createItem]; // 獲取新的對象在 allItem 數組中的索引 NSInteger lastRow = [[[JXItemStore sharedStore] allItem] indexOfObject:newItem]; NSIndexPath * indexPath = [NSIndexPath indexPathForRow:lastRow inSection:0]; // 將新航插入 UITableView 對象 [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationBottom]; [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO]; } @end
接着我麼設置天極愛一個編輯按鈕,用來替換 Edit 按鈕。
#import "JXItemsViewController.h" #import "JXItem.h" #import "JXItemStore.h" #import "JXDetailViewController.h" @interface JXItemsViewController () /** 頭部視圖 */ @property (nonatomic,weak) UIView * headerView; /** 編輯按鈕 */ @property (nonatomic,strong) UIButton * editButton; /** 增長按鈕 */ @property (nonatomic,strong) UIButton * addButton; @end @implementation JXItemsViewController - (instancetype)init { // 調用父類的指定初始化方法 self = [super initWithStyle:UITableViewStylePlain]; if (self) { UINavigationItem * navItem = self.navigationItem; navItem.title = @"JXHomepwner"; // 建立新的 UIBarButtonItem 對象 // 將其目標對象設置爲當前對象,將其多作方法設置爲指定方法 UIBarButtonItem * bdi = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addClick:)]; // 爲 UINavigationItem 對象的 rightBarButtonItem 屬性賦值 // 指向新建立的 UIBarButtonItem 對象 navItem.rightBarButtonItem = bdi; UIBarButtonItem * edit = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:@selector(editClick:)]; navItem.leftBarButtonItem = edit; for (NSInteger i=0; i<5; i++) { [[JXItemStore sharedStore] createItem]; } } return self; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self.tableView reloadData]; } - (void)viewDidLoad { [super viewDidLoad]; // 向控制器註冊 [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"UITableViewCell"]; // 加載頭視圖 [self headerView]; } #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [[[JXItemStore sharedStore] allItem] count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // 建立 UITableViewCell 對象,風格使用默認風格 UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell" forIndexPath:indexPath]; // 獲取 allItem 的第 n 個 JXItem 對象 // 而後將該 JXItem 對象的描述信息賦值給 UITableViewCell 對象的 textLabel // 這裏的 n 是該 UITableViewCell 對象所對應的表格索引 NSArray * items = [[JXItemStore sharedStore] allItem]; JXItem * item = items[indexPath.row]; cell.textLabel.text = [item description]; return cell; } /** * 刪除行 * * @param tableView 對象 * @param editingStyle 操做 * @param indexPath 操做的行數 */ - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { // 若是tableView請求的是刪除對象 if (editingStyle == UITableViewCellEditingStyleDelete) { // 取出須要刪除的對象 NSArray * items = [[JXItemStore sharedStore] allItem]; JXItem * item = items[indexPath.row]; // 刪除對象 [[JXItemStore sharedStore] removeItem:item]; // 刷新表格 [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; } } /** * 移動行 * * @param tableView 對象 * @param sourceIndexPath 須要移動的行 * @param destinationIndexPath 目標行 */ - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath { [[JXItemStore sharedStore] moveItemAtIndex:sourceIndexPath.row toIndex:destinationIndexPath.row]; } #pragma mark - UITalbeViewDelegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { JXDetailViewController * detailController = [[JXDetailViewController alloc] init]; NSArray * items = [[JXItemStore sharedStore] allItem]; JXItem * selectedItem = items[indexPath.row]; // 將選中的JXItem 對象賦給 DetailViewController 對象 detailController.item = selectedItem; // 將新建立的控制器壓入到導航控制器對象棧中 [self.navigationController pushViewController:detailController animated:YES]; } #pragma mark - 懶加載 - (UIView *)headerView{ if (_headerView == nil) { UIView * headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 50)]; // 設置頭部視圖 self.tableView.tableHeaderView = headerView; headerView.backgroundColor = [UIColor cyanColor]; [headerView addSubview:self.editButton]; [headerView addSubview:self.addButton]; _headerView = headerView; } return _headerView; } - (UIButton *)editButton{ if (_editButton == nil) { _editButton = [UIButton buttonWithType:UIButtonTypeCustom]; _editButton.frame = CGRectMake(0, 0, self.view.bounds.size.width / 2, 50); [_editButton setTitle:@"Edit" forState:UIControlStateNormal]; _editButton.backgroundColor = [UIColor greenColor]; [_editButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [_editButton addTarget:self action:@selector(editClick:) forControlEvents:UIControlEventTouchDown]; } return _editButton; } - (UIButton *)addButton{ if (_addButton == nil) { UIButton * addButton = [UIButton buttonWithType:UIButtonTypeCustom]; addButton.frame = CGRectMake(self.view.bounds.size.width / 2, 0, self.view.bounds.size.width / 2, 50); [addButton setTitle:@"Add" forState:UIControlStateNormal]; addButton.backgroundColor = [UIColor blueColor]; [addButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [addButton addTarget:self action:@selector(addClick:) forControlEvents:UIControlEventTouchDown]; _addButton = addButton; } return _addButton; } #pragma mark - 點擊事件 - (void)editClick:(UIButton *)sender {
- (void)editClick:(UIBarButtonItem *)sender { if (self.isEditing) { // 若是是編輯狀態,取消編輯 // 更改文字 [sender setTitle:@"Edit" forState:UIControlStateNormal]; // 取消編輯 [self setEditing:NO animated:YES]; } else { // 更改文字 [sender setTitle:@"Done" forState:UIControlStateNormal]; // 開始編輯 [self setEditing:YES animated:YES]; } } /** * 添加表格時,必須保證 UITableView 對象當前顯示的行數與數據源的提供的行數相同。 * 因此,在添加以前,必須先建立一個新的 JXItem 對象並加入到 JXItemStore 中 * * @param sender 按鈕 */ - (void)addClick:(UIButton *)sender { // 建立新的 JXItem 對象,並加入到 JXItemStore 中 JXItem * newItem = [[JXItemStore sharedStore] createItem]; // 獲取新的對象在 allItem 數組中的索引 NSInteger lastRow = [[[JXItemStore sharedStore] allItem] indexOfObject:newItem]; NSIndexPath * indexPath = [NSIndexPath indexPathForRow:lastRow inSection:0]; // 將新航插入 UITableView 對象 [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationBottom]; [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO]; } @end
構建並運行