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.13.2012

UITableView 中移動項目的方法

  

延續之前與 UITableView 相關的文章,你可以在「索引式搜索」中的「元件設定」分類裡找到所有有關 UITableView 的文章,UITableView 支援項目新增、移動、與刪除等操作,而本篇要介紹的是 UITableView 中項目的移動方法,之前已經介紹過 UITableView 編輯功能中的新增與刪除方法,為了能有更完整的介紹,將延續之前的程式碼,如果表格對應的資料結構有任何問題,可以參考文章 UITableView 的分類顯示 Sections 一文,來瞭解範例程式碼中的資料結構。


注意事項
在開始撰寫刪除程式碼之前,請務必確認以下項目:
  • 對應的操作陣列形態必須是 NSMutableArray
UITableView 在做移動項目的動作時,我們同樣也需要對陣列裡的元素作移動的動作,由於傳統的 NSArray 提供的方法函式已不敷使用,應此在陣列的形態上請務必都宣告成 NSMutableArray,如果你的陣列也同時包含巢狀結構,也請務必確認所有子結構下的陣列形態都是 NSMutableArray。
  • 陣列結構的正確性
由於每次在對 UITableView 做移動項目的動作時,表格的內容都會隨即更新,也就是會重新執行那些表格基本設定的方法函式,像是設定表格的欄位數目、分類數目等等,如果你陣列的結構有錯誤,無法與 UITableView 相互對應,例如 index 錯誤無法在陣列中找到資料等問題,程式會出現 crash 的可能。
  • 移動陣列元素作順序
在做移動陣列元素的操作上,我們所使用的方法是「先移除該元素」之後陣列中「插入該元素」,透過這兩個步驟來完成陣列元素的移動,然而元陣列素的移動並沒有硬性規定的做法,但是操作上的先後順序會引想你陣列的索引值,進而造成資料的顯示錯誤。另外你也可以使用 NSMutableArray 的 moveObjectsAtIndexes:toIndex: 方法函式來幫助元素做移動。
掌握以上技巧之後,下面就可以開始撰寫移動表格項目的程式碼了。


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


開啓表格項目的移動功能
在啓用表格的編輯功能之後,雖然可以進入表格的編輯模式,但是還不能對表格中的項目進行移動,所以還必須透過下列 UITableView 中內建的方法函式來啟用表格項目的移動功能,你也可以透過此方法函式,針對每個表格中的項目,設定它們能否被移動,如範例圖片(右)裡的點我增加項目,並沒有被賦予移動的功能。
//開啟表格項目的移動功能
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {

    //設定表格分類中的最後一個項目不能被「移動」
    if (indexPath.row == [[heroicaArray objectAtIndex:indexPath.section] count]) {
        return NO;
    } else {
        return YES;
    }
}


實作項目移動的方法
透過下列 UITableView 中內建的方法函式來實作項目的移動,其中我們針對「錯誤的移動位置」會跳警告加以提示,錯誤的移動方式包含跨分類的移動,與項目移動到「不可以移動項目」的下方,如下圖。

錯誤的移動位置-移動到「不可移動的項目下方」

這樣做的原因是因為,「不可移動項目」是我們在表格處於編輯狀態時動態產生的,若是冒然將項目移動到它的下方,不但沒有意義,還會因此使陣列的索引值錯亂。
//實作項目移動
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {

    //判斷項目「是否在同一分類中移動」與「是否移動到到正確的位置」
    if (fromIndexPath.section == toIndexPath.section && toIndexPath.row < [[heroicaArray objectAtIndex:toIndexPath.section] count]) {

        //移動項目
        id item = [[heroicaArray objectAtIndex:fromIndexPath.section] objectAtIndex:fromIndexPath.row];
        [[heroicaArray objectAtIndex:fromIndexPath.section] removeObjectAtIndex:fromIndexPath.row];
        [[heroicaArray objectAtIndex:toIndexPath.section] insertObject:item atIndex:toIndexPath.row];
    } else {

        //發出警告
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示"
                                                        message:@"錯誤的項目移動位置"
                                                       delegate:nil
                                              cancelButtonTitle:@"確定"
                                              otherButtonTitles:nil];
        [alert show];

        [self.tableView reloadData];
    }
}

這裡有個小技巧,在判斷表格項目移動的位置為「錯誤的移動位置」時,雖然說程式碼並沒有實作移動的方法,但是實際上在使用者介面的部分表格已經移動到該位置了,所以才能取得目的地的索引值供我們判斷使用,這時可以透過 reloadData 方法函式,幫助我們重新整理表格的內容,來還原剛剛錯誤的操作。

另外你也可以使用 NSMutableArray 的 moveObjectsAtIndexes:toIndex: 方法函式來幫助陣列中的元素做移動。
NSIndexSet *index = [NSIndexSet indexSetWithIndex:fromIndexPath.row];
[[heroicaArray objectAtIndex:fromIndexPath.section]moveObjectsAtIndexes:index toIndex:toIndexPath.row];/code>






沒有留言:

張貼留言