最近在寫一個輕量級的網絡遊戲,遇到了技能優先順序手動排序的需求,我就想到了iOS自帶的tableView編輯功能,對其進行了初步探索,最後作出的效果以下圖所示:數組
點擊左邊能夠刪除,拖住右邊能夠手動排序,要實現這個功能,分如下步驟。網絡
①用plist存儲這些數據,能夠看到數據分兩個職業,每一個職業4個技能,所以創建以下的plist結構:atom
②由於每一個職業除了技能還有名稱這個屬性,所以應該用職業模型保存一個職業的全部數據,再用一個數組保存全部職業模型,職業模型的定義以下:spa
#import <Foundation/Foundation.h> @interface Vocation : NSObject @property (nonatomic, strong) NSString *title; @property (nonatomic, strong) NSMutableArray *skills; + (instancetype)vocationWithDict:(NSDictionary *)dict; @end須要注意的是這裏沒有利用系統實現KVC,由於若是採用系統自帶的,在把plist中的NSArray傳給NSMutableArray時,由於NSMutableArray沒有初始化 ,因此就變成了不可變的數組,這樣爲後面的順序調整帶來了致命的問題,所以咱們手動實現KVC,用NSArray初始化一個NSMutableArray 。
#import "Vocation.h" @implementation Vocation + (instancetype)vocationWithDict:(NSDictionary *)dict{ Vocation *vc = [[Vocation alloc] init]; vc.title = dict[@"title"]; vc.skills = [NSMutableArray arrayWithArray:dict[@"skills"]]; return vc; } @end③使用一個TableViewController,而且實現下面的代碼:
#import "TableViewController.h" #import "Vocation.h" @interface TableViewController () @property (nonatomic, strong) NSArray *vocations; @end @implementation TableViewController - (void)viewDidAppear:(BOOL)animated{ [super viewDidAppear:animated]; self.editing = YES; } - (BOOL)prefersStatusBarHidden{ return YES; } - (NSArray *)vocations{ if (_vocations == nil) { NSString *path = [[NSBundle mainBundle] pathForResource:@"skillList.plist" ofType:nil]; NSArray *dictArray = [NSArray arrayWithContentsOfFile:path]; NSMutableArray *vocations = [NSMutableArray array]; for (NSDictionary *dict in dictArray) { Vocation *vc = [Vocation vocationWithDict:dict]; [vocations addObject:vc]; } _vocations = vocations; } return _vocations; } - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ return self.vocations.count; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ Vocation *vc = self.vocations[section]; return vc.skills.count; } - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{ Vocation *vc = self.vocations[section]; return vc.title; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *ID = @"vocation"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID]; } // 在這裏設置cell數據 Vocation *vc = self.vocations[indexPath.section]; cell.textLabel.text = vc.skills[indexPath.row]; return cell; } - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{ if (sourceIndexPath.section != destinationIndexPath.section) { [self.tableView reloadData]; return; } Vocation *vc = self.vocations[sourceIndexPath.section]; [vc.skills exchangeObjectAtIndex:sourceIndexPath.row withObjectAtIndex:destinationIndexPath.row]; } - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{ if (editingStyle == UITableViewCellEditingStyleDelete) { Vocation *vc = self.vocations[indexPath.section]; [vc.skills removeObjectAtIndex:indexPath.row]; } [self.tableView reloadData]; } - (IBAction)editClick:(id)sender { UIBarButtonItem *btn = sender; if ([btn.title isEqualToString:@"調整"]) { btn.title = @"肯定"; self.editing = YES; }else{ btn.title = @"調整"; self.editing = NO; [self.tableView reloadData]; } } @end在這其中,editClick:對應了NavigationBar上的按鈕,用於切換編輯和非編輯狀態。
經過tableViewController的editing方法控制是否進入編輯狀態。code
要實現拖動排序,須要實現下面的方法,不然不能拖動,在這個方法中能夠獲取到起始和終止位置。排序
須要注意的是移動只是單純的視覺效果,實際的數據源變化須要本身調整,不然在從新加載數據後又會回到原來的順序,可經過數組的exchangeObjectAtIndexPath::方法調整。
遊戲
爲了不組間移動,這裏進行了判斷,發現非法移動直接重置數據。
rem
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{ if (sourceIndexPath.section != destinationIndexPath.section) { [self.tableView reloadData]; return; } Vocation *vc = self.vocations[sourceIndexPath.section]; [vc.skills exchangeObjectAtIndex:sourceIndexPath.row withObjectAtIndex:destinationIndexPath.row]; }