UITableView 单选

一个单选的需求,虽说不到一个下午又被砍掉了,还是记录下

UITableView 单选_第1张图片
单选例图

整个写下来说白了就是对 Cell 获取的 IndexPath 的实现和改变,所以首先分析下一般我们是怎样获取 cell 上的 indexPath的

1、通过 Tag 值直接获取

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    RadioCell *cell =[tableView dequeueReusableCellWithIdentifier:@"RadioCellIden" forIndexPath:indexPath];
    cell.tag = indexPath.row;
    [cell.radioButton addTarget:self action:@selector(radioSelectedWithRow:) forControlEvents:UIControlEventTouchUpInside];
    return cell;
}

直接明显,但当数目量多的时候,且包含 section 的时候,就非常不爽了,而且这明显是 cell 中的事情,拿出来干嘛呢,同时这也不是直接拿到IndexPath 的,不推荐。

2、通过 在 Cell 中通过其父视图获取

- (void)raidoSelectAction:(UIButton *)button {
    UITableView *tableView = (UITableView *)button.superview.superview.superview.superview;
    NSIndexPath *indexPath = [tableView indexPathForCell:self];
}

这样写,我可以明白为什么会有四个 superView的,但是有时我们不一定能想明白,而且 iOS7之前在此处是只要三个 superView,对于UITableViewWrapperView 出现当初是坑了不少人的,所以对于这种写法,也是不推荐的。

3、通过cell 中传来 tableView 再来获取 IndexPath

@interface RadioCell : UITableViewCell
@property (nonatomic, weak) UITableView *tableView;
@end
- (void)raidoSelectAction:(UIButton *)button {
    NSIndexPath *indexPath = [self.tableView indexPathForCell:self];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    RadioCell *cell =[tableView dequeueReusableCellWithIdentifier:@"RadioCellIden" forIndexPath:indexPath];
    cell.tableView = tableView;
    return cell;
}

我是推荐这种写法的,只是需要多传一次而已。

部分完整代码
#import 

@class RadioModel;
@protocol RadioSelectDelegate;

@interface RadioCell : UITableViewCell

@property (nonatomic, weak) UITableView *tableView;
@property (nonatomic, weak) id  delegate;
@property (nonatomic, strong) RadioModel *model;

@end

@protocol RadioSelectDelegate 

- (void)radioSelectedWithIndexPath:(NSIndexPath *)indexPath;

@end
#import "RadioCell.h"
#import 
#import "RadioModel.h"

@interface RadioCell ()

@property (nonatomic, strong) UIButton *radioButton;
@property (nonatomic, strong) UILabel *nameLabel;

@end

@implementation RadioCell

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        _radioButton = [UIButton buttonWithType:UIButtonTypeCustom];
        [_radioButton setImage:[UIImage imageNamed:@"like_default"] forState:UIControlStateNormal];
        [_radioButton setImage:[UIImage imageNamed:@"like_selected"] forState:UIControlStateSelected];
        [_radioButton addTarget:self action:@selector(raidoSelectAction:) forControlEvents:UIControlEventTouchUpInside];
        [self.contentView addSubview:_radioButton];
        [_radioButton mas_makeConstraints:^(MASConstraintMaker *make) {
            make.centerY.equalTo(self.contentView.mas_centerY);
            make.leading.mas_equalTo(@20);
            make.size.mas_equalTo(CGSizeMake(40, 40));
        }];
        
        _nameLabel = [[UILabel alloc] init];
        [self.contentView addSubview:_nameLabel];
        [_nameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
            make.leading.mas_equalTo(_radioButton.mas_trailing).offset(20);
            make.trailing.mas_equalTo(@(-20));
            make.centerY.equalTo(_radioButton.mas_centerY);
            make.height.mas_equalTo(@30);
        }];
    }
    return self;
}

- (void)raidoSelectAction:(UIButton *)button {
    // 改变状态
    button.selected = !button.selected;
    // 当被选中的时候
    if (button.selected) {
        // 获取 indexPath
        NSIndexPath *indexPath = [self.tableView indexPathForCell:self];
        if (self.delegate && [self.delegate respondsToSelector:@selector(radioSelectedWithIndexPath:)]) {
            [self.delegate radioSelectedWithIndexPath:indexPath];
        }
    }
}

- (void)setModel:(RadioModel *)model {
    self.radioButton.selected = model.isSelected;
    self.nameLabel.text = model.titleString;
}

@end
#import 

@interface RadioModel : NSObject

@property (nonatomic, copy) NSString *titleString;
@property (nonatomic, assign) BOOL isSelected;

@end

此 TableView 处,只需要瞧瞧下面两个方法就 OK 了

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    RadioCell *cell =[tableView dequeueReusableCellWithIdentifier:RadioTableViewIden forIndexPath:indexPath];
    cell.tableView = tableView;
    cell.delegate = self;
    cell.model = self.dataArray[indexPath.row];
    return cell;
}
- (void)radioSelectedWithIndexPath:(NSIndexPath *)indexPath {
    NSIndexPath *tempIndexPath = self.lastIndexPath;
    // 改变上一次的
    if (tempIndexPath && tempIndexPath != indexPath) {

        RadioModel *model =  self.dataArray[tempIndexPath.row];
        model.isSelected = NO;
        [self.tableView reloadRowsAtIndexPaths:@[tempIndexPath] withRowAnimation:UITableViewRowAnimationNone];
    }
    // 记住这一次的
    RadioModel *model =  self.dataArray[indexPath.row];
    model.isSelected = YES;
    [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
    self.lastIndexPath = indexPath;
   // TODO : 接下来可以保存你选中的做需要做的事情。
}

总的说来,就是对 IndexPath 的获取,小小记录下
PS:另外看到了runtime添加属性方式,获取 IndexPath,感觉怪怪的,用 runtime 的思路是 OK 的,但是此处它里面的实现确实可以调整的。

你可能感兴趣的:(UITableView 单选)