UITableViewCell中KVO的使用

最近做项目要实现一个列表中完成单选的需求,就是列表中显示的是乘机人信息,每次只允许选择一个人,然后进行后续操作。乘机人信息展示采用的是自定义Cell,最前面是个单选按钮,然后是姓名,证件号等信息。首先定义一个私有属性来存放当前选择的索引:

NSIndexPath* _selectedIndex;

 

点击整个Cell来实现单选的功能,逻辑比较简单,只需在didSelectRowAtIndexPath方法中调用单选按钮的点击事件,并记录当前Cell的indexPath。如果之前点选的是别的index,还需将之前的点选给置为未选中状态。

 

- (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath {

   

    SelectCell *cell = (SelectCell *)[self.tableView cellForRowAtIndexPath:indexPath];

    [cell SelectedButton:cell.selectButton];

   

    if(_selectedIndex) {

        if(_selectedIndex == indexPath) {

           _selectedIndex = nil;

        }else {

           SelectCell *lastSelectedCell = (SelectCell *)[self.tableViewcellForRowAtIndexPath:_selectedIndex];

            [lastSelectedCellSelectedButton:lastSelectedCell.selectButton];

           _selectedIndex = indexPath;

        }

    } else{

       _selectedIndex = indexPath;

    }

}

 

可是若是点击每个Cell的单选按钮,该如何处理呢?

 

我考虑了以下几种解决方案:

1、将cell的单选按钮的enabled属性置为NO,如此一来,该按钮就不接受点击事件,点击它就相当于点击整个cell,走didSelectRowAtIndexPath的逻辑。不过,按钮(UIButton)的enabled属性被置为NO以后,它的背景图片变暗,这样点选的效果不好。解决变暗的问题,需要设置其Disabled的背景图片和正常状态下一样。如下:

 

UIImage* image=[button imageForState:UIControlStateNormal];

[button setImage: image forState:UIControlStateDisabled];

 

由于使用的是共通的自定义Cell,为了不影响其他页面的正常使用,故放弃该方案。

 

2、将按钮(UIButton)控件置换为图形控件(UIImageView),这样每次点选只需要替换UIImageView的背景图即可,因为也需要变更自定义Cell,故也放弃。

 

3、使用代理。将对于单选按钮的点击事件,通过代理传递回ViewController类,执行和点击整个Cell时调用的方法didSelectRowAtIndexPath一样的逻辑即可。一样不愿意对共通的自定义Cell进行修改,故放弃。

 

4、使用KVO的方式。每次点选单选按钮,该按钮的selected状态都会发生变化,通过对其selected属性值变化进行监听,以实现单选逻辑。需要对每个页面中显示出来的cell进行监听,并在该cell不显示时进行监听的移除。代码如下:

 

- (void)tableView:(UITableView*)tableView willDisplayCell:(UITableViewCell*)cell forRowAtIndexPath:(NSIndexPath *)indexPath {

   

    [((SelectCell *)cell).selectButton addObserver:self forKeyPath:@"selected" options:NSKeyValueObservingOptionNew context:nil];

}

 

- (void)tableView:(UITableView*)tableView didEndDisplayingCell:(UITableViewCell*)cell forRowAtIndexPath:(NSIndexPath*)indexPath {

    [((SelectCell *)cell).selectButton removeObserver:self forKeyPath:@"selected"];

}

 

在监听事件中实现单选的逻辑,代码如下:

 

#pragma mark - observe value for key path

- (void)observeValueForKeyPath:(NSString*)keyPath

                      ofObject:(__unused id)object

                        change:(NSDictionary*)change

                       context:(void*)context

{

    if([keyPath isEqualToString:@"selected"]){

        UIButton *btn = (UIButton *)object;

        NSIndexPath*indexPath = [JLTools indexPathFromTag:btn.tag];

       

        if (_selectedIndex) {

            if (_selectedIndex ==indexPath) {

               _selectedIndex = nil;

           } else {

               SelectCell * lastSelectedCell = (SelectCell *)[self.tableView cellForRowAtIndexPath:_selectedIndex];

               [lastSelectedCell SelectedButton:lastSelectedCell.selectButton];

               _selectedIndex = indexPath;

           }

        } else {

            _selectedIndex =indexPath;

        }

    }

}

 

写完测试,功能OK。不过点击页面后退按钮时却发现程序崩溃了?!原因是没有对页面中显示的Cell的监听事件进行移除。所以还需要下dealloc方法中进行移除监听事件。代码如下:

 

- (void)dealloc {

    NSArray*cells = [self.tableView visibleCells];

    for (int i= 0; i < cells.count; i++) {

        SelectCell *cell= (SelectCell *)cells[i];

       

        [cell.selectButton removeObserver:self forKeyPath:@"selected"];

    }

}

 

貌似使用了比较复杂的方式解决了一个简单的问题,不过还是很开心自己学会了如何对Cell中的内容使用KVO的方式进行监听。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值