注意事项:
1,在cellForRowAtIndexpath里如果未对cell中的控件赋值,由于重用的原因,会出现界面错乱
2, 解决方案:model里存储的控件要显示的内容每次cell重用,根据model重新赋值,
3,当cell上的控件发生变化时,及时修改model
重用cell经常会出现重用错误的现象,下面就通过代码的形式帮助解决一下这个问题
原理就是通过将cell中的值放在一个数组中,通过数组的方式不断控制cell(下面通过两种不同的方式来解决这个问题)
第一步创建一个A对象
@interface A : NSObject
@property (nonatomic, assign)BOOL on;
@end
里面只有一个属性。控制开关的开与关
第二步创建一个自定义cell
@interface CustomCell : UITableViewCell
// 开关
@property (nonatomic, retain) UISwitch *s;
// 索引
@property (nonatomic, retain) NSIndexPath *indexPath;
@end
实现代码,在cell上添加一个开关
@implementation CustomCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
_s = [[UISwitch alloc] initWithFrame:CGRectMake(200, 10, 60, 20)];
[self.contentView addSubview:_s];
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
@end
第三步定义一个UITableViewController对象
@interface TableViewController : UITableViewController<CustomCellDelegate>
@property (nonatomic, retain)NSMutableArray *arr;
@end
只有一个用来保存信息的数组
实现
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// 默认开关的状态为关,把开关状态信息添加到数组中
self.arr = [NSMutableArray arrayWithCapacity:30];
for (int i = 0 ; i < 30; i++) {
A *a = [[A alloc] init];
a.on = NO;
[self.arr addObject:a];
}
// Custom initialization
}
return self;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
[cell.s addTarget:self action:@selector(changeState:) forControlEvents:UIControlEventValueChanged];
}
// indexPath中存储的是所在的行和列
cell.indexPath = indexPath;
A *a = [self.arr objectAtIndex:indexPath.row];
// 通过改变值得方式改变cell的内容(只要数组中值不变,就不会发生)
cell.s.on = a.on;
return cell;
}
- (void)changeState:(UISwitch *)s
{
// 通过获取的cell(中保存的indexPath来获取数组中对应的元素)
CustomCell *cell = (CustomCell *)(s.superview.superview.superview);
A *a = [self.arr objectAtIndex:cell.indexPath.row];
a.on = s.on;
}
以上方法是方法一
方法二通过代理的方式来实现重用机制
在自定义cell中写一个协议
@protocol CustomCellDelegate <NSObject>
// 开关事件(参数为开关对象和索引对象)
- (void)switchDidClick:(UISwitch *)s atIndexPath:(NSIndexPath *)indexPath;
@end
@interface CustomCell : UITableViewCell
// 开关
@property (nonatomic, retain) UISwitch *s;
// 索引
@property (nonatomic, retain) NSIndexPath *indexPath;
// 代理对象
@property (nonatomic, assign) id<CustomCellDelegate>delegate;
方法体中
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
_s = [[UISwitch alloc] initWithFrame:CGRectMake(200, 10, 60, 20)];
[self.contentView addSubview:_s];
[_s addTarget:self action:@selector(changeState:) forControlEvents:UIControlEventValueChanged];
// Initialization code
}
return self;
}
- (void)changeState:(UISwitch *)s
{
// 返回调用cell所在indexPath中的内容(当前cell所在的indexPath)
[_delegate switchDidClick:s atIndexPath:_indexPath];
}
通过传递开关对象和所在的索引地址来确定所需要获取的数组的对象
@interface TableViewController : UITableViewController<CustomCellDelegate>
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.delegate = self;
}
// 创建后进行复制操作(索引)
cell.indexPath = indexPath;
A *a = [self.arr objectAtIndex:indexPath.row];
cell.s.on = a.on;
return cell;
}
- (void)switchDidClick:(UISwitch *)s atIndexPath:(NSIndexPath *)indexPath
{
A *a = [self.arr objectAtIndex:indexPath.row];
// 获取A对象的具体位置,通过switch的具体操作值来进行数组中元素的修改
a.on = s.on;
}
以上方式就可以解决cell重复被使用的问题