1. Cell View的實現
這邊介紹比較簡單的方式來實作Cell View。從Storyboard新增一個Navigation Controller,可以看到實際上新增的是兩個Controller:Navigation Controller以及Table View Controller。
I. 3個Section搭配0個Row
II. 0個Section搭配3個Row
III. 1個Section搭配3個Row
IV. 2個Section分別搭配1個和2個Row
實驗中可以發現Table的Section與Row其實有些潛規則(很多書上都沒講):
- Row可以為0,但是Section必須大於0,否則看不到Section和Row
- 一定要實作titleForHeaderInSection()才能看到Section,而且必須return非nil以及非@""內容的字串
- 一定要實作cellForRowAtIndexPath(),否則執行時一定會crash
- 一定要在Storyboard裡面Cell的ID設定成與.m底下cellForRowAtIndexPath()裡面的ID一致,否則編譯可以通過但執行時會crash
這裡放上以“2個Section分別搭配1個和2個Row”為例子的程式:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
if (section == 0)
return 1;
else if (section == 1)
return 2;
return 3;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [NSString stringWithFormat:@"%d", section+1];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
cell.textLabel.text = [NSString stringWithFormat:@"%d", indexPath.row];
return cell;
}
2. 動態加入Cell View的方法
為了能紀錄每個Cell對應的內容並動態增減Cell,必須先建立一個矩陣來存放資料。矩陣的使用方式與Table很相近。建立Table View Controller對應的.h和.m(這裡取名TestTable作為例子)之後,在.m宣告一個NSMutableArray。
#import "TestTable.h"
@interface TestTable ()
{
NSMutableArray *dataArray;
}
@end
接著填入本篇第一個教學「Cell View的實現」裡面提到的幾個重要函式的內容與回傳值。首先,必須得配置記憶體給剛宣告的dataArray,因此在一開始就會被執行的viewDidLoad()底下,必須配置記憶體給dataArray並初始化。接著numberOfSectionsInTableView()一定要大於零才能顯示Cell,所以即使不需要section也還是得回傳1。numberOfRowsInSection()則是為了正確顯示矩陣的內容,所以將矩陣的內容數量當作Cell數量的回傳值。cellForRowAtIndexPath()是用來產生Cell實體的函式,一般會在這底下設定Cell顯示的內容。
- (void)viewDidLoad
{
[super viewDidLoad];
dataArray = [[NSMutableArray alloc] init];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [dataArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
NSString *text = [dataArray objectAtIndex:indexPath.row];
cell.textLabel.text = [NSString stringWithFormat:@"%@", text];
return cell;
}
#import <UIKit/UIKit.h>
@interface TestTable : UITableViewController
@property (weak, nonatomic) IBOutlet UITableView *TestTableView;
@end
接著宣告一個可以讓Storyboard認得到的函式,然後在Storyboard的Navigation Bar上新增一個按鈕並將此按鈕的Sent Actions指到此函式。需注意的是如果少了呼叫reloadData,則按下按鈕只會增加矩陣dataArray的內容,但畫面上的Cell數量並不會改變。
- (IBAction)addCell:(id)sender
{
[dataArray addObject:[NSString stringWithFormat:@"%d", [dataArray count]+1]];
[self.TestTableView reloadData];
}
可參考Youtube教學影片:http://www.youtube.com/watch?v=YEaxIVv-EPI
3. 點擊Cell怎麼連結到另一個顯示詳細內容的View
讓Cell全部轉場至同一個View的方法很簡單,只要在Storyboard上面直接將Cell拉藍線到創建的詳細內容View即可,不論新增多少個Cell,點擊都可以轉場至所連線的頁面。
4. 怎麼區分是點擊哪個Cell並且顯示對應內容?
本篇第3點教學是不管點擊哪個Cell都會轉場至同一個View。一般開發需求是希望這同一個View會因為來自不同的Cell而能顯示不同的內容。這裡有兩種方法可以實現:
- 使用Xcode預設函式didSelectRowAtIndexPath() + viewDidAppear()
- 或是不照第3點教學建議的方式,改成不透過Storyboard建立View,而是當函式didSelectRowAtIndexPath()被呼叫時才動態建立View
- 使用者點擊
- 轉場過程中,執行View A的函式prepareForSegue()
- 轉場的View B執行viewDidLoad()
- 執行View A的didSelectRowAtIndexPath()
- 執行View B的viewDidAppear()
另個不遵照教學3的方式則是不透過Segue來換場至View B。此方式不會有閃爍的缺點,但必須在Storyboard之外的地方另行建立一個長得像Storyboard的xib檔案。xib只會實作自己的View,接著就要以程式的方式來開啓此View。
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
aaa = [dataArray objectAtIndex:indexPath.row];
MjToolDetailView *detailTableViewController = [[MjToolDetailView alloc] initWithNibName:@"MjToolDetailView" bundle:nil];
[self.navigationController pushViewController:detailTableViewController animated:YES];
}
5. 使用刪除鍵移除Cell View的方法
一旦可以動態增加Cell後,接下來就會需要刪除Cell。
- 要如何在Navigation Bar上面加一個刪除按鈕
- 這個按鈕按下去要能出現讓使用者刪除Cell的功能
- (void)viewDidLoad
{
[super viewDidLoad];
self.editButtonItem.title = @"編輯";
self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
由此可以看出,editButtonItem以及navigationItem是個預設就存在的物件,也就是說它們本來就存在Navigation Controller裡面,所以我們要做的事情就是讓editButtonItem成為navigationItem右邊的一個按鈕。只要Cell裡面有東西,則點選"編輯"按鈕之後可看到Cell左邊出現"減號"。按下"減號",Cell右邊會出現"Delete",然而此鍵在實作之前是沒有功用的。附帶一點,不點選"編輯"而是用手指由左往右滑動一樣可以看到"Delete"鍵。
接著來想辦法讓Delete鍵生效。Xcode幫你創建Table View Controller的.m檔裡面有個commitEitingStyle()函式,如下,預設此函式是被註解起來的,拿掉註解符號就可以使用此函式。
/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
重點來了,這個動作僅能刪除UI上的Cell,但對應後面的資料庫內容通常也需要跟著被刪除。因此必須在editingStyle == UITableViewCellEditingStyleDelete判斷式裡面加入從資料庫或是先前宣告的矩陣中刪除一筆資料。所以程式碼會長得像下面:
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[dataArray removeObjectAtIndex:indexPath.row];
[self sqlDelData];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
使用removeObjectAtIndext刪除dataArray的一筆資料,另外存放在資料庫的資料就得實作另個函式來方便處理,這部分可以參考下面介紹資料庫函式FMDB的連結:
- http://www.minwt.com/ios/5079.html
- http://bonjouryentinglai.wordpress.com/2011/03/20/fmdb:我的sqlite救星/
6. 更改Table View上方Navigator Bar的Button文字的方法
前面有介紹將editButtonItem設定成Navigator Bar右邊按鈕或是左邊按鈕的方法,
self.navigationItem.rightBarButtonItem = self.editButtonItem;
self.navigationItem.leftBarButtonItem = nil;
只要更改editButtonItem的內容就可以更改Navigator Bar上按鈕的文字:
self.editButtonItem.title = @"編輯";
- (void)setEditing:(BOOL)editing animated:(BOOL)animate
{
[super setEditing:editing animated:animate];
if(editing)
{
self.editButtonItem.title = @"完成";
}
else
{
self.editButtonItem.title = @"編輯";
}
}
沒有留言:
張貼留言