en

hi, it seems you are using microsoft internet explorer. it doesn't match web standard and causes problems browsing this site. please please please use mozilla firefox or google chrome instead. thank you!

zh

哦哦!您正在使用Internet Explorer 瀏覽器,它與我們的網頁標準並不相容,可能會導致畫面顯示不正常。
請改用 Mozilla Firefox 或者 Google Chrome 才能正常瀏覽本網站,謝謝!

2.10.2012

動態增加 UITableView 中項目的方法

  

延續之前與 UITableView 相關的文章,你可以在「索引式搜索」中的「元件設定」分類裡找到所有有關 UITableView 的文章,UITableView 支援項目新增、移動、與刪除等操作,而本篇要介紹的是新增項目的方法,在此提供兩種方法來動態新增表格內的項目:透過 UIBarButtonItem 與按下編輯表格時增加一個新增項目的欄位。


注意事項
在開始撰寫刪除程式碼之前,請務必確認以下項目:
  • 對應的操作陣列形態必須是 NSMutableArray 
UITableView 在做新增項目的動作時,我們同樣也需要對陣列裡的元素作新增的動作,由於傳統的 NSArray 並不支援 addObject: 方法函式,應此在陣列的形態上請務必都宣告成 NSMutableArray,如果你的陣列也同時包含巢狀結構,也請務必確認所有子結構下的陣列形態都是 NSMutableArray。 
  • 陣列結構的正確性
由於每次在對 UITableView 做新增項目的動作時,表格的內容都會隨即更新,也就是會重新執行那些表格基本設定的方法函式,像是設定表格的欄位數目、分類數目等等,如果你陣列的結構有錯誤,無法與 UITableView 相互對應,例如 index 錯誤無法在陣列中找到資料等問題,程式會出現 crash 的可能。
  • 任何時候都應先對陣列操作,之後才是 UITableView
原因同上,如果先對 UITableView 進行操作,在更新表格內容時極有可能出現無法與陣列內元素對應的情形,在新增表格項目中一個比較好的做法, 就是先改變陣列內的元素,在直接呼叫 UITableView 的 reloadData 方法函式,來重新顯示表格的資料。
掌握以上技巧之後,下面就可以開始撰寫動態新增表格項目的程式碼了。


開啟編輯表格的功能
在未啓用此功能之前,使用者只能點選表格項目來顯示詳細資料,有關其他新增、刪除、移動等功能都無法使用,若要開啓表格的互動功能,可以使用以下內建的方法函式,並回傳一個 YES 的布林值即可(預設值為 NO)。
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    return YES;
}


使用 UIBarButtonItem 來新增項目
透過使用 UIBarButtonItem 做新增項目的動作方法非常簡單,只要製作一個 UIBarButtonItem 並設定他所要觸發的方法函式,之後在其方法函式中對陣列增加想要的元素,之後在使用 UITableView 的 reloadData 方法函式來更新表格資訊即可。

下列程式碼是在 Navigation Bar 的左邊加上一個 UIBarButtonItem,並且設定按鈕按下時所要觸發的方法函式 addHeroicaItem,你可以將增加 UIBarButtonItem 的程式碼撰寫在 viewDidLoad 方法函式中。
- (void)viewDidLoad {
    [super viewDidLoad];

    [self setTitle:@"LEGO Heroica"];

    //製作增加項目的UIBarButtonItem
    UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addHeroicaItem)];
    [self.navigationItem setLeftBarButtonItem:addButton];

    //資料初始化
    roleArray = [[NSMutableArray alloc] initWithObjects:@"野蠻人", @"法師", @"弓箭手", @"盜賊", @"德魯伊", @"騎士", nil];
    monsterArray = [[NSMutableArray alloc] initWithObjects:@"哥布林戰士", @"哥布林護衛", @"哥布林軍官", @"哥布林王", @"黑暗德魯伊", @"狼人", @"傀儡護衛", @"傀儡領主", @"蜘蛛", @"蝙蝠", nil];

    heroicaArray = [[NSMutableArray alloc] initWithObjects:roleArray, monsterArray, nil];
}

//在每個分類裡都添加一筆資料
- (void) addHeroicaItem {
    for (id item in heroicaArray) {
         [item addObject:@"被增加的項目"];
    }

    [self.tableView reloadData];
}

現在每當按下 UIBarButtonItem 之後,表格內所有分類都會在最後增加一個名為「被增加的項目」的項目。


透過在編輯表格時的新增項目欄位
此方法是希望在對表格按下「編輯」時,可以出現新增欄位的選項,方便使用者做新增欄位的動作,雖然說這是一個很不錯的做法,但是執行起來卻相對複雜,我們將分成以下幾個步驟來實作。


*重新設定顯示資料的數目
由於我們希望再按下表格的編輯按鈕時,能夠動態替每個分類增加一個欄位,好讓使用者點選並新增資料,因此表格是否處於編輯狀態,它所顯示的資料數目也不盡相同,我們可以利用 self.tableView.editing 來判斷目前表格是否處於編輯狀態,設定回傳不同的欄位數目。
//設定資料數目
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (self.tableView.editing) {
        return [[heroicaArray objectAtIndex:section] count] +1;
    } else {
        return [[heroicaArray objectAtIndex:section] count];
    }
}


*重新設定顯示的資料內容
原因同上,在按下表格的編輯按鈕時,所顯示的資料會比實際陣列中的資料多1,而多的這一比資料,就是用來新增欄位的項目。下面程式碼是判斷該欄位如果是該分類的最後一個時,就將欄位名稱設定成「點我增加項目」。
// 設定資料內容
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    //製作可重復利用的表格欄位Cell
    static NSString *CellIdentifier = @"CellIdentifier";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    //設定按編輯時的新增欄位
    if (self.tableView.editing && indexPath.row == [[heroicaArray objectAtIndex:indexPath.section] count]) {
        cell.textLabel.text = @"點我增加項目";
    } else {
        cell.textLabel.text = [[heroicaArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
    }

    cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
    return cell;
}


*設定項目編輯時的類型
項目預設的編輯類型是 UITableViewCellEditingStyleDelete,也就是刪除,但是我們的最後一個項目的編輯類型可不能是刪除,它必須是 UITableViewCellEditingStyleInsert,我們才能動態對表格新增資料,若要設定項目編輯時的類型,可以透過 UITableView 內建的方法函式並回傳一個 UITableViewCellEditingStyle 參數來設定。
//設定編輯時的類型
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.row == [[heroicaArray objectAtIndex:indexPath.section] count]) {
        return UITableViewCellEditingStyleInsert;
    } else {
        return UITableViewCellEditingStyleDelete;
    }
}


*實作新增項目的程式碼
透過下列另一個內建的 UITableView 方法函式,撰寫在選擇新增項目之後所要處理動作的程式碼,同樣也是先對陣列增加元素,再去呼叫 UITableView 的 reloadData 方法函式,來重新顯示表格的資料,與之前的方法不同的是,在此新增的項目只針對該分類,並非所有分類。
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

    //判斷編輯表格的類型為「新增」
    if (editingStyle == UITableViewCellEditingStyleInsert) {
        [[heroicaArray objectAtIndex:indexPath.section] addObject:@"被增加的項目"];
        [self.tableView reloadData];
    }
}


*重新製作表格的「編輯」按鈕
到目前為止已經完成新增項目的程式碼,但是仍有一個小問題在,就是當按下「編輯」按鈕時,表格雖然處於編輯狀態,但是並沒有出現新的項目好讓使用者操作,有就是表格並沒有 reloadData 重新繪製,原因是之前使用 self.navigationItem.rightBarButtonItem = self.editButtonItem 所製作出來的標準按扭,並不會觸發 UITableView 的 reloadData 方法函式,因此,現在我們要重新製作表格的「編輯」按鈕,你可以在 viewDidLoad 方法函式中撰寫以下製作「編輯」按鈕的程式碼。
//改寫編輯按鈕
UIBarButtonItem *editButton = [[UIBarButtonItem alloc] initWithTitle:@"編輯" style:UIBarButtonItemStyleBordered target:self action:@selector(editHeroicaItem)];
[self.navigationItem setRightBarButtonItem:editButton];

接著是按下按鈕所觸發的方法函式,在方法函式中利用 self.tableView.editing 參數來判斷表格是否處於編輯狀態,並依照表格現在的狀態來設定按鈕的文字,最後是表格編輯狀態的切換與資料的更新。
- (void)editHeroicaItem {
    if (self.tableView.editing) {
        [self.navigationItem.rightBarButtonItem setTitle:@"編輯"];
    } else {
        [self.navigationItem.rightBarButtonItem setTitle:@"完成"];
    }

    [self.tableView setEditing:!self.tableView.editing];
    [self.tableView reloadData];
}

上述程式碼中,既使你使用 setEditing: animated: 方法還函式,表格在進入或是離開編輯狀態時,同樣也不會出現漸變的動畫,原因是因為表格索項目不一致所導致的。


關於新增項目的內容
文章中只有示範如何動態增加 UITableView 中的項目,並沒有對所要新增項目的內容加以琢磨,關於新增項目的內容都是給予固定值,若是你想要替項目設定不同的內容,可以在些關鍵的程式碼處開啓新的 View 來對陣列作設定,之後再去呼叫 UITableView 的 reloadData 方法函式,重新顯示表格的內容。






沒有留言:

張貼留言