最近在写一个轻量级的网络游戏,遇到了技能优先顺序手动排序的需求,我就想到了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]; }