延續之前與 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>
沒有留言:
張貼留言