有关UITableViewCell的侧滑删除以及使用相关大神框架MGSwipeTableCell遇到的小问题

提起笔,却不知道从何写起了,今天一整天都耗费在了这个可能根本不算是问题的小问题上,至今仍有一种蛋蛋的忧桑。。(噢,不是提笔,是键盘手T_T)
  表格视图在项目中就像是每日的家常便饭,在cell上添加侧滑删除功能这种需求也是遍地可见。而就是这么一个家常菜却坑了我一天,可能我是真的闲的蛋疼吧,好吧,其实,讲道理还是我太菜,人艰不拆。
  好了废话不多说,运用系统自带的API实现侧滑删除功能其实非常简单:

//- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
 {// 
// if (editingStyle == UITableViewCellEditingStyleDelete) {
//
 // 删除数据源对应模型
// [self.shops removeObjectAtIndex:indexPath.row];
// 从tableView中删除
// [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationTop]; 
// }
//
 //}

只要重写上述代理方法,实现删除模式的相关处理即可,当然你也可以加一个else语句对于编辑模式不是删除时做一些其他的处理,比如控制台提示,或者是处理其它模式,比如插入insert,并且上述代码也可以不从tableView中删除,直接从数据源中删除,然后刷新表格就好了[tableView reloadData];这里我个人认为苹果的deleteRowsAtIndexPaths:方法肯定是有它的好处的,试想,数据很多的话,我们为了删除tableView中的一行,而刷新整个表格,这样真的好吗?另,上述只是最简单的处理情况,倘若数据很多,本地有数据库存储,在上述基础上还要进行数据库的删除和存储操作,同样的,如果数据源是从服务器获取的,那么还要相关请求删除服务器上的数据,不然下次来到该界面,删掉的数据又会显示。

  从iOS8开始,苹果开放了这样一个API:

- (nullable NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath

返回一个UITableViewRowAction数组,每一个"Action"代表一个侧滑删除的Button。这样侧滑每一行Cell可以有更多按钮提供给用户交互。

不幸地是这个API只在iOS8才有,这样iOS8以下就没办法使用到这种效果。这种情况下我们不得不使用第三方库或者自己重写UITableViewCell来“模拟”出这种效果。那其实呢,我今天所要得需求是最基本的只有删除就OK的,但是我是自定义的cell,然后我遇到一个问题,就是滑动cell,删除按钮很难出现,十次能不能滑出一次还是个问题。

  我项目中自定义的cell如上图,至于为什么会划不出删除按钮,可以参见我上篇博客,翻译国外大神的文章制作一个可以滑动操作的 Table View Cell
  一般情况下只要你重写了- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {}方法,不实现也可以滑出按钮。那对于这样一个简单地需求我们完全可以自定义一个cell去实现它,思路很简单,可以在系统的UITableViewCell基础上添加一个ScrollView,再添加需要的菜单按钮,或者通过在系统的cell上添加滑动手势,监听来实现。我今天浪费了很多时间,其中有一个原因是原本我想自己封装一套的,结果发现要想真正写好一个框架其实并非易事,看似简单地功能需求,你要考虑的问题可能会很多。
  我最后选择了使用第三方框架, 找了几个对比看了一下,https://github.com/MortimerGoro/MGSwipeTableCell 这个算是封装的比较成熟的了,支持多种侧滑方式以及立体等各种效果 。他里面封装了MGSwipeTableCell和MGSwipeButton,你只需要让你的cell继承于MGSwipeTableCell,然后像这样在tableView的数据源方法里面,创建cell的同时,给它配置侧滑菜单需要的buttons数组传给它就行。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{ 
static NSString * reuseIdentifier = @"programmaticCell"; MGSwipeTableCell * cell = [self.tableView dequeueReusableCellWithIdentifier:reuseIdentifier]; 
if (!cell) {
 cell = [[MGSwipeTableCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:reuseIdentifier]; } 
cell.textLabel.text = @"Title"; cell.detailTextLabel.text = @"Detail text"; cell.delegate = self; 
//optional 
//configure left buttons
 cell.leftButtons = @[[MGSwipeButton buttonWithTitle:@"" icon:[UIImage imageNamed:@"check.png"] backgroundColor:[UIColor greenColor]], [MGSwipeButton buttonWithTitle:@"" icon:[UIImage imageNamed:@"fav.png"] backgroundColor:[UIColor blueColor]]]; 

cell.leftSwipeSettings.transition = MGSwipeTransition3D; 
//configure right buttons
 cell.rightButtons = @[[MGSwipeButton buttonWithTitle:@"Delete"     backgroundColor:[UIColor redColor]], [MGSwipeButton   buttonWithTitle:@"More" backgroundColor:[UIColor lightGrayColor]]]; 

 cell.rightSwipeSettings.transition = MGSwipeTransition3D; 
 return cell;}

监听菜单里面button的点击事件,作者提供了两种选择,一种就是在上述代码中设置cell的代理,实现它的一些代理方法;另一种更方便就MGSwipeButton
里提供了一个block回调,你可以在初始化MGSwipeButton的时候添加它

[MGSwipeButton buttonWithTitle:@"More" backgroundColor:[UIColor lightGrayColor] callback:^BOOL(MGSwipeTableCell *sender) { NSLog(@"Convenience callback for swipe buttons!");}]

他提供的接口非常完善,具体的可以在MGSwipeTableCell和MGSwipeButton的.h文件里面看。我今天选择的就是使用block,一开始遇到的问题见如下代码,注释

-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{ 
MyShopCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
 cell.shop = self.shops[indexPath.row]; 
cell.myDelegate = self; 
cell.rightButtons = @[[MGSwipeButton buttonWithTitle:@"删除" backgroundColor:[UIColor magentaColor] padding:50 callback:^BOOL(MGSwipeTableCell *sender) { 
[self.shops removeObjectAtIndex:indexPath.row]; NSLog(@"%d-------%@",self.shops.count ,self.shops);
// 当我用这个方法删除时,偶尔会崩溃,具体原因不明 测试了很多遍,感觉是删太快就会出现,也可能是快速点击两次删除会出现,总之很奇怪,慢慢地一个一个删一般不会有问题(总之,用户正常使用的话,不影响,当时也没强行深究原因,暂且记下一笔)
 [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationTop];
//当我用这个方法删除时,好像没有什么问题,问题出在哪呢?(再后来发现好像也有崩溃
// [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:indexPath.row inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
//不用删除方法,直接强行刷新表格,好像没出过bug
// [tableView reloadData]; return true;
 }],
 ]; 
cell.rightSwipeSettings.transition = MGSwipeTransition3D; 
return cell;
}

因为这是个概率性出现的bug,我这种菜鸟,在那无脑的尝试,瞎捣腾,试了度娘上的各种事实证明并不相关的方法,后来我干脆自己胡乱猜想,我当时还曾以为是线程里面的数据冲突,崩溃就崩在[self.shops removeObjectAtIndex:indexPath.row];这句上,就是说可能是我删除的indexPath.row时候那一行已经删除了,我又猜想是不是delete的时候读数据跟写数据冲突,我给block里面所有跟控制器有关的指针的__weak关键字,我甚至煞笔地给tableView的数据源方法加了锁,同时给我block里面删除操作都lock起来,最后把自己都锁煞笔了(其实,我对锁的使用并不熟练,而且我只在多线程里面偶有用到)总之一下午倒腾总结起来就一个字:然并卵!
  好了,废话不多了,我这日记写的越来越像博客了0.0.。。。。
  最后:

-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{ 
MyShopCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
 cell.shop = self.shops[indexPath.row];
 cell.myDelegate = self;
 __weak typeof(self) weakSelf = self; 
cell.rightButtons = @[[MGSwipeButton buttonWithTitle:@"删除" backgroundColor:[UIColor magentaColor] padding:50 callback:^BOOL(MGSwipeTableCell *sender) {
}]
];

之前我在这个数据源方法里面写的,block里面使用的indexPath都是数据源方法
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath中传进来的参数

[weakSelf.shops removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];

然后我仔细一看发现第三方的哪个cell 叫我传得button数组 button后面的方法里面 传的block回调有个参数sender 把cell 传进来了,我用lldb命令打印了一下 发现 两个indexPath 并不一样



  因为是第一次用这个框架,一开始我还奇怪他block 为什么要传个sender 我在数据源方法里面本来能拿到,不是多余的吗 然后我刚刚脑子一热就试了下 发现没有崩溃了。但是不知道 为什么偶尔会崩,没崩的时候两者indexPath是一样的 ,我又猜想应该是跟cell的重用机制有关吧。具体确定的原因尚不明确,不过好在问题总算解决了,哎,还有有种蛋蛋的忧伤 ,废了一整天 解决了这么一个小问题还没搞清楚本质。
  博文在此,日后必会解决地一清二楚,暂且记下,问题很小,我很菜,跟我一样的新手遇到了可以避免这坑,大神误入请略过。。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,475评论 4 372
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,744评论 2 307
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,101评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,732评论 0 221
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,141评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,049评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,188评论 2 320
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,965评论 0 213
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,716评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,867评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,341评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,663评论 3 263
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,376评论 3 244
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,200评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,990评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,179评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,979评论 2 279

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,650评论 4 59
  • 1.nav1.navigationBar.barStyle=UIBarStyleBlack; //改变导航栏背景颜...
    SadMine阅读 1,499评论 1 4
  • 2017.02.22 可以练习,每当这个时候,脑袋就犯困,我这脑袋真是神奇呀,一说让你做事情,你就犯困,你可不要太...
    Carden阅读 1,255评论 0 1
  • 手上有许多小疤,长短不一,大小不一,还挺有意思的。
    叶开开阅读 134评论 0 0
  • 哇次哟累阅读 84评论 0 0