有一个朋友昨天问我一个问题,说他在做商城项目或者在cell上添加开关或其他控件是,控件会由于cell的复用问题,引起开关状态被复用。于是,我就写了一个Demo。胡乱写的,代码不是很规范。当然这里面顺便解决了有些人说的“如何确定点击的button在哪个cell上的问题”。当然除了文中的方法,朋友又提供了另一种解决“如何确定点击的button在哪个cell上的问题”的方法:http://stackoverflow.com/questions/7504421/getting-row-of-uitableview-cell-on-button-press
接下来继续我们的主题。
自定义一个cell
#import <UIKit/UIKit.h>
@protocol SwitchIsOnDelegate <NSObject>
-(void)SwitchIsOn:(BOOL)isOn andRow:(NSInteger)row;
@end
@interface MyTableViewCell : UITableViewCell
@property (strong,nonatomic) IBOutletUILabel *nameLabel;
@property (strong,nonatomic) IBOutletUISwitch *statuSwitch;
@property (weak,nonatomic)id <SwitchIsOnDelegate>delegate;
@property (strong,nonatomic) UITableView * tableView;
#import "MyTableViewCell.h"
@implementation MyTableViewCell
- (void)awakeFromNib {
[self.statuSwitchsetOn:NO];
// Initialization code
}
- (IBAction)switchChange:(UISwitch *)sender {
//取出开关所在的这个cell
UIView * view1 = [[sender superview] superview];
MyTableViewCell * cell =(MyTableViewCell *) view1;
//在根据cell取出cell所在的行,这里的tableView是在vc里通过属性传值传过来的。
NSIndexPath * indexPathAll = [self.tableViewindexPathForCell:cell];//获取cell对应的row
//代理方法传值,在vc里进行某些操作
[self.delegateSwitchIsOn:[sender isOn] andRow:indexPathAll.row];
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selectedanimated:animated];
// Configure the view for the selected state
}
@end
#import "ViewController.h"
#import "MyTableViewCell.h"
@interface ViewController ()<UITableViewDataSource,UITableViewDelegate,SwitchIsOnDelegate>
@property (nonatomic,strong)UITableView * tableView;
@property (nonatomic,strong)NSMutableArray * dataSource;
@property (nonatomic,strong)NSMutableDictionary * statusSource;
@end
@implementation ViewController
- (void)viewDidLoad {
[superviewDidLoad];
[self initData];
[selfcreateView];
}
-(void)initData
{
//为了方便测试,我写成了这种形式,你也可以自定义一个可变字典来接收switch的状态
self.dataSource = [[NSMutableArrayalloc] initWithArray:@[[[NSMutableDictionaryalloc] initWithDictionary:@{@"name":@"夜间模式"}],[[NSMutableDictionaryalloc] initWithDictionary:@{@"name":@"大字体"}],[[NSMutableDictionaryalloc] initWithDictionary:@{@"name":@"锁屏时振动"}],[[NSMutableDictionaryalloc] initWithDictionary:@{@"name":@"锁屏时振动"}],[[NSMutableDictionaryalloc] initWithDictionary:@{@"name":@"xxxx7"}],[[NSMutableDictionaryalloc] initWithDictionary:@{@"name":@"锁屏时振动"}],[[NSMutableDictionaryalloc] initWithDictionary:@{@"name":@"锁屏时振动"}],[[NSMutableDictionaryalloc] initWithDictionary:@{@"name":@"锁屏时振动"}],[[NSMutableDictionaryalloc] initWithDictionary:@{@"name":@"锁屏时振动"}],[[NSMutableDictionaryalloc] initWithDictionary:@{@"name":@"锁屏时振动"}],[[NSMutableDictionaryalloc] initWithDictionary:@{@"name":@"锁屏时振动"}],[[NSMutableDictionaryalloc] initWithDictionary:@{@"name":@"锁屏时振动"}],[[NSMutableDictionaryalloc] initWithDictionary:@{@"name":@"锁屏时振动"}],[[NSMutableDictionaryalloc] initWithDictionary:@{@"name":@"锁屏时振动"}],[[NSMutableDictionaryalloc] initWithDictionary:@{@"name":@"锁屏时振动"}],[[NSMutableDictionaryalloc] initWithDictionary:@{@"name":@"锁屏时振动"}]]];
}
-(void)createView
{
self.tableView = [[UITableViewalloc] initWithFrame:self.view.boundsstyle:UITableViewStyleGrouped];
self.tableView.delegate =self;
self.tableView.dataSource =self;
[self.viewaddSubview:self.tableView];
[self.tableViewregisterNib:[UINibnibWithNibName:@"MyTableViewCell"bundle:nil]forCellReuseIdentifier:@"cell"];
}
- (void)didReceiveMemoryWarning {
[superdidReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - UITableViewDelegate & UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.dataSource.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString * identifier =@"cell";
MyTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:identifier];
//这里顺便提一下self.xxx和_xxx的用法区别
/*
1、在对象内部读取数据时,应该直接通过实例变量来读,而写入数据时,则应该通过属性来写。
2、在初始化方法及dealloc方法中,总是应该直接通过实例变量来读写数据。
3、有时会使用惰性初始化技术配置某份数据,这种情况下,需要通过属性来读取数据。
*/
//这里是cell的属性传值
cell.tableView =_tableView;
cell.delegate = self;
cell.nameLabel.text = [[self.dataSourceobjectAtIndex:indexPath.row]objectForKey:@"name"];
//这里判断switch的状态键值对有没有增加进去
if ([[self.dataSourceobjectAtIndex:indexPath.row]count] >1) {
BOOL ison = [[[self.dataSourceobjectAtIndex:indexPath.row]objectForKey:@"switchStatu"]integerValue];
[cell.statuSwitch setOn:ison];
}else
{
[cell.statuSwitch setOn:NO];
}
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 70;
}
#pragma mark - SwitchisOnDeelgate
//代理方法,接收并将开关状态放入对应row的键值对。也可以再自定义一个字典来存放。
- (void)SwitchIsOn:(BOOL)isOn andRow:(NSInteger)row
{
[[self.dataSourceobjectAtIndex:row] setObject:@(isOn)forKey:@"switchStatu"];
}
@end
虽然写的比较啰嗦,但是相信需要的人肯定能看懂,