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 <Foundation/Foundation.h>

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 <UIKit/UIKit.h>
#import "CustomerModel.h"

NS_ASSUME_NONNULL_BEGIN

//設置一個代理,用於將textField中d輸入的值傳遞到Ccontroller中去處理
@protocol CustomerCellDelegate <NSObject>

@optional

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

@end

@interface CustomerCell : UITableViewCell

//創建model對象
@property (nonatomic, strong)CustomerModel *model;

//聲明代理
@property (nonatomic, weak) id<CustomerCellDelegate> delegate;

@end

NS_ASSUME_NONNULL_END

CustomerCell.m

#import "CustomerCell.h"

@interface CustomerCell()<UITextFieldDelegate>
{
    //聲明兩個視圖
    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 ()<UITableViewDelegate, UITableViewDataSource, CustomerCellDelegate>//添加協議
{
    //聲明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<UITouch *> *)touches withEvent:(UIEvent *)event{
    [self.view endEditing:YES];
}

@end

上面的代碼就足以解決cell中有textField時因爲cell複用二產生的問題,當然還有別的方法可以解決這個問題,這裏就不多說了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章