iOS基础控件--UITableView关于cell中带有UITextField的处理

在上一篇文章的最后有说到在cell中带有UITextField的时候,在cell的复用机制下会有一些问题。关于这个问题的解决其实我们可以参照cell的复用机制。说的有点绕哈。。。
解决复用带来的问题,还是用复用的机制,确实挺饶人的。下面来详细说一下。
上一篇文章中的代码和文字已经介绍了复用机制,在tableView中的cell都有一个id作为表示,在tableView中展示出来的cell也都有一个唯一的表示,那就是:indexPath。展示出来的每一个cell都有一个indexPath,所以我们的解决办法就是利用这个indexPath。原理和复用池很像,下面说原理:
我们可以设计一个数据模型(model)类,用于存放我们每一个cell中textField中输入的文字,这个model类中设置一个属性为:indexPath,这个属性和cell的indexPath对应,每一个cell上的indexPath和textField输入的文字就可以作为一个model类的对象存入一个数组中。这样就可以将数组中model类的每一个对象和cell一一对应。当滚动时就不会出现已经输入的文字消失的问题了。
仔细想一想上面的这个model数组,是不是和复用池有点相似。下面我们就代码实现以下。
首先创建一个model类
CustomerModel.h

#import 

NS_ASSUME_NONNULL_BEGIN

@interface CustomerModel : NSObject

@property (nonatomic, strong) NSString *text;
@property (nonatomic, strong) NSIndexPath *index;

- (instancetype)initWithDict:(NSDictionary *)dict;

@end

NS_ASSUME_NONNULL_END

CustomerModel.m

#import "CustomerModel.h"

@implementation CustomerModel

- (instancetype)initWithDict:(NSDictionary *)dict {
    self = [super init];
    if (self) {
        _text = dict[@"text"];
        _index = dict[@"index"];
        
        [self setValuesForKeysWithDictionary:dict];
    }
    
    return self;
}

- (void)setValue:(id)value forUndefinedKey:(NSString *)key {}

@end

然后自定义cell
CustomerCell.h

#import 
#import "CustomerModel.h"

NS_ASSUME_NONNULL_BEGIN

//设置一个代理,用于将textField中d输入的值传递到Ccontroller中去处理
@protocol CustomerCellDelegate 

@optional

- (void)textFieldCellText:(NSString *)text index:(NSIndexPath *)index;

@end

@interface CustomerCell : UITableViewCell

//创建model对象
@property (nonatomic, strong)CustomerModel *model;

//声明代理
@property (nonatomic, weak) id delegate;

@end

NS_ASSUME_NONNULL_END

CustomerCell.m

#import "CustomerCell.h"

@interface CustomerCell()
{
    //声明两个视图
    UITextField *textField;
}
@end

@implementation CustomerCell


//重写init方法
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
    //调用父类init方法创建
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        self.backgroundColor = [UIColor yellowColor];
        //创建成功则给cell添加需要的子视图
        textField = [[UITextField alloc] init];
        textField.delegate = self;
        textField.backgroundColor = [UIColor whiteColor];
        textField.borderStyle = UITextBorderStyleLine;
        [self.contentView addSubview:textField];
    }
    
    return self;
}

//重写layoutSubviews方法,给视图设置位置大小
- (void)layoutSubviews{
    textField.frame = CGRectMake(20, 5, 200, 30);
}

//代理方法
- (void)textFieldDidEndEditing:(UITextField *)textField{
    if ([self.delegate respondsToSelector:@selector(textFieldCellText:index:)]) {
        //这里讲textField中输入的内容和model中存储的index传递到controller
        [self.delegate textFieldCellText:textField.text index:_model.index];
    }
}

//model对象赋值
- (void)setModel:(CustomerModel *)model{
    _model = model;
    textField.text = model.text;
}

- (void)awakeFromNib {
    [super awakeFromNib];
    // Initialization code
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

@end

在controller中调用

#import "ViewController.h"
#import "CustomerCell.h"
#import "CustomerModel.h"

@interface ViewController ()//添加协议
{
    //声明tableView和数据源
    UITableView *table;
    NSMutableArray *dataSource;
}
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self createDataSource];
    [self createTableView];
}

//创建数据源
- (void)createDataSource{
    //初始化数据源数组
    dataSource = [NSMutableArray arrayWithCapacity:0];
    //循环创建model,s初始设置text为空,并编号index
    for (int i = 0; i < 20; i++) {
        CustomerModel *model = [[CustomerModel alloc] init];
        model.text = @"";
        NSIndexPath *index = [NSIndexPath indexPathForRow:i inSection:0];
        model.index = index;
        [dataSource addObject:model];
    }
}

//创建tableView视图
- (void)createTableView{
    //创建并设置位置大小和风格形式
    table = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
    //设置代理
    table.delegate = self;
    table.dataSource = self;
    //设置纵横滑块不显示
    table.showsVerticalScrollIndicator = NO;
    table.showsHorizontalScrollIndicator = NO;
    [self.view addSubview:table];
}

#define mark --UITableViewDelegate
//设置列表中每个元素的行高,在非动态行高的情况下设置固定值。动态行高的情况需要计算。
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return 64;
}

//设置列表中元素的个数  一般设置为数据源中元素的个数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return dataSource.count;
}

//创建tableView中的每一个cell,这里使用复用机制。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    CustomerCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
    if (cell == nil) {
        cell = [[CustomerCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
    }
    cell.model = dataSource[indexPath.row];
    cell.delegate = self;
    
    return cell;
}

//代理回调,比对indexPath将对应的text进行修改保存
- (void)textFieldCellText:(NSString *)text index:(NSIndexPath *)index{
    for (int i = 0; i < dataSource.count; i++) {
        CustomerModel *model = dataSource[i];
        if (index == model.index) {
            model.text = text;
        }
    }
}

//收起键盘
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    [self.view endEditing:YES];
}

//收起键盘
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    [self.view endEditing:YES];
}

@end

上面的代码就足以解决cell中有textField时因为cell复用二产生的问题,当然还有别的方法可以解决这个问题,这里就不多说了。

你可能感兴趣的:(OC,iOS)