我正在尝试创建一个UITableViewController子类,通过我的应用程序设置向我提供UITableView。在重新加载有关UISwtitch状态的数据时遇到问题。
该表有3个部分:
第1节 - 不断一行
第2节 - 第一行中的UISwitch 使这一部分由1或3组成 行(取决于状态 UISwitch)
第3节 - 第一行中的UISwitch 使这一部分由1或3组成 行(取决于状态 UISwitch),但与另一个UISwitch 和其他行数据。
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
switch ( section )
{
case 0:
return 1;
break;
case 1:
if ( limit_password_attempts )
return 3;
else
return 1;
break;
case 2:
if ( lock_when_inactive )
return 3;
else
return 1;
break;
default:
return 1;
break;
}
}
第二和第三部分第一排的两个UISwitch-s分别改变BOOL
BOOL limit_password_attempts;
BOOL lock_when_inactive;
我的问题是当我在第二部分中转换UISwitch(用于exmpl)时,我希望我的第二部分再扩展2行,并填充新数据。它延伸,但新细胞看起来不像我想要的。第二行成为下一节中的第一行的副本(第一行带有UISwitch的第三节),如果第三节之前未扩展,则第三行返回正确,如果是,则该行变为第三部分第二行的副本。
所以我的单元格自定义看起来像这样,我猜错误就在这里。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;
static NSString *EnabledCellIdentifier = @"Enabled";
cell = [tableView dequeueReusableCellWithIdentifier:EnabledCellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc]
initWithStyle: UITableViewCellStyleDefault
reuseIdentifier: EnabledCellIdentifier]
autorelease];
cell.detailTextLabel.enabled = YES;
switch ( indexPath.section )
{
case 0: // section 1
cell.textLabel.text = @"Banks settings";
break;
case 1: // section 2
{
switch ( indexPath.row )
{
case 0:
{
cell.textLabel.text = @"Limit passwords attempts";
UISwitch* actSwitch = [[UISwitch alloc] initWithFrame: CGRectZero ];
[cell setEditingAccessoryView: actSwitch];
[actSwitch setTag: indexPath.section];
[actSwitch addTarget: self
action: @selector(actSwitchChanged:)
forControlEvents: UIControlEventValueChanged];
[self.view addSubview:actSwitch];
[actSwitch setOn:YES animated:NO];
[actSwitch setOn:NO animated:NO];
actSwitch.on = NO;
[cell addSubview: actSwitch];
cell.accessoryView = actSwitch;
[actSwitch release];
break;
}
case 1:
cell.textLabel.text = @"Lock after 3 atempts";
break;
case 2:
cell.textLabel.text = @"Lock for 30 min";
break;
default:
break;
}
break;
}
case 2: // section 3
{
switch ( indexPath.row )
{
case 0:
{
cell.textLabel.text = @"Lock when inactive";
UISwitch* pactSwitch = [[UISwitch alloc] initWithFrame: CGRectZero ];
[cell setEditingAccessoryView: pactSwitch];
[pactSwitch setTag: indexPath.section];
[pactSwitch addTarget: self
action: @selector(actSwitchChanged:)
forControlEvents: UIControlEventValueChanged];
[self.view addSubview:pactSwitch];
[pactSwitch setOn:YES animated:NO];
[pactSwitch setOn:NO animated:NO];
pactSwitch.on = NO;
[cell addSubview: pactSwitch];
cell.accessoryView = pactSwitch;
[pactSwitch release];
break;
}
case 1:
cell.textLabel.text = @"Lock when inactive for 20 min";
break;
case 2:
cell.textLabel.text = @"Unlock key";
break;
default:
break;
}
break;
}
default:
NSLog(@"%d", indexPath.section );
break;
}
}
return cell;
}
看起来有一些隐藏在我的数组中的行数据,这就是填充onec,而表控制器以某种方式更新表,具体取决于出现的行,只更新它们。在部分中添加行时,为什么会进行复制。这就像是一个阵列中的节点。我认为它必须向前推进细胞,但不仅仅是复制。 我是否要以某种方式删除行以使这种表更新? 我想我在这里错过了一些基本的东西。一些MVC概念?但这里是否真的有必要建立数据模型?为什么?如果是,那我该怎么做呢?
感谢您的回答。 祝你有个美好的一天。
这是在我的代码中。我只是没有在我的问题中写下来。 在UISwtitch切换后调用reloadData方法:
[pactSwitch setTag: indexPath.section];
[actSwitch addTarget: self
action: @selector(actSwitchChanged:)
forControlEvents: UIControlEventValueChanged];
在actSwitchChanged方法中:
-(void) actSwitchChanged: (UISwitch*) pSwitch {
if ( [pSwitch tag] == 1 ) //section 2
limit_password_attempts = !limit_password_attempts ;
else if ( [pSwitch tag] == 2 ) //section 3
lock_when_inactive = !lock_when_inactive;
[self.tableView reloadData];
}
所以reloadData确实会改变viewTable的内容,但它不是我想象的那样。
有什么想法吗?
答案 0 :(得分:4)
数据模型总是存在......即使它只是UITableView调用的一堆if语句。我认为这种区别导致了这个问题。
您的布尔值代表您的基础数据模型。与数据模型的所有更改一样,您必须让表视图知道基础数据何时更改。
每当您更改一个布尔值时,请尝试添加以下呼叫。
[myTableViewController.tableView reloadData];
答案 1 :(得分:3)
你是对的,你实现了- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
的错误。如果您正在寻找简单的方法来实现具有不同布局的单元格而无需UITableViewCell
的子类化,那么您需要,例如:
0)阅读this以深入理解UITableView编程
1)方法为每个布局返回一种单元格
- (NSString*)typeOfCellForIndexPath:(NSIndexPath*)indexPath {
NSString *ret = @"CellWithoutSwitch";
if(indexPath.section != 0 && idextPath.row == 0) {
ret = @"CellWithSwitch";
}
return ret;
}
2)方法返回每种类型的单元格
- (UITableViewCell*)cellForType:(NSString*)aType {
UITableViewCell *cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier: aType] autorelease];
cell.detailTextLabel.enabled = YES;
if ([aType isEqualToString:@"CellWithSwitch"]) {
// just copy of your code
// this does not need here
cell.textLabel.text = @"Limit passwords attempts";
// this needs but with CGRectMake(...) insted of CGRectZero
UISwitch* actSwitch = [[UISwitch alloc] initWithFrame: CGRectZero ];
// this does not need
[cell setEditingAccessoryView: actSwitch];
// this needs but for switch tag you should use #define SWITCH_TAG 777
[actSwitch setTag: indexPath.section];
// this does not need here
[actSwitch addTarget: self
action: @selector(actSwitchChanged:)
forControlEvents: UIControlEventValueChanged];
// wrong part of code
[self.view addSubview:actSwitch];
// this does not need here
[actSwitch setOn:YES animated:NO];
// wrong part of code
[actSwitch setOn:NO animated:NO];
actSwitch.on = NO;
// ok
[cell addSubview: actSwitch];
// wrong part of code
cell.accessoryView = actSwitch;
// ok
[actSwitch release];
}
}
3)配置具有路径
的单元的方法 - (void)cofigureCell:(UITableViewCell*)cell forIndexPath:(NSIndexPath*)indexPath {
// just copy of your code
switch ( indexPath.section )
{
case 0: // section 1
cell.textLabel.text = @"Banks settings";
break;
case 1: // section 2
{
switch ( indexPath.row )
{
case 0:
{
cell.textLabel.text = @"Limit passwords attempts";
/* this part of code replace with UISwitch* actSwitch = (UISwitch*)[cell viewWithTag:SWITCH_TAG];
UISwitch* actSwitch = [[UISwitch alloc] initWithFrame: CGRectZero ];
[cell setEditingAccessoryView: actSwitch];
[actSwitch setTag: indexPath.section];*/
[actSwitch addTarget: self
action: @selector(actSwitchChanged:)
forControlEvents: UIControlEventValueChanged];
/* all what you need now that cofigure an state of switch with limit_password_attempts variable - [actSwitch setOn:limit_password_attempts animated:NO];
// this is junk
[self.view addSubview:actSwitch];
[actSwitch setOn:YES animated:NO];
[actSwitch setOn:NO animated:NO];
actSwitch.on = NO;
[cell addSubview: actSwitch];
cell.accessoryView = actSwitch;
[actSwitch release];*/
break;
}
case 1:
cell.textLabel.text = @"Lock after 3 atempts";
break;
case 2:
cell.textLabel.text = @"Lock for 30 min";
break;
default:
break;
}
break;
}
case 2: // section 3
{
switch ( indexPath.row )
{
case 0:
{
// look at previous configuration of switch
cell.textLabel.text = @"Lock when inactive";
UISwitch* pactSwitch = [[UISwitch alloc] initWithFrame: CGRectZero ];
[cell setEditingAccessoryView: pactSwitch];
[pactSwitch setTag: indexPath.section];
[pactSwitch addTarget: self
action: @selector(actSwitchChanged:)
forControlEvents: UIControlEventValueChanged];
[self.view addSubview:pactSwitch];
[pactSwitch setOn:YES animated:NO];
[pactSwitch setOn:NO animated:NO];
pactSwitch.on = NO;
[cell addSubview: pactSwitch];
cell.accessoryView = pactSwitch;
[pactSwitch release];
break;
}
case 1:
cell.textLabel.text = @"Lock when inactive for 20 min";
break;
case 2:
cell.textLabel.text = @"Unlock key";
break;
default:
break;
}
break;
}
default:
NSLog(@"%d", indexPath.section );
break;
}
}
4)实施最后一个方法
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;
// get type for indexPath
static NSString *EnabledCellIdentifier = [self typeOfCellForIndexPath:idextPath];
cell = [tableView dequeueReusableCellWithIdentifier:EnabledCellIdentifier];
if (cell == nil)
{
// create a cell with needed type
cell = [self cellForType:EnabledCellIdentifier];
}
// cofigure the cell
[self cofigureCell:cell forIndexPath:indexPath];
return cell;
}
答案 2 :(得分:0)
Gaj,谢谢你的回答。
它帮助了我,当我改变UISwitch条件时,表正确地重新加载。
但我必须更改uiswitch的标签,因为我确实需要区分我在actSwitchChanged
方法中处理的UISwitch,以了解它是limit_password_attempts
还是lock_when_inactive
我想将来不会出现问题?我的意思是,这里覆盖了SWITCH_TAG。
而且,为什么我需要#define SWITCH_TAG 777
是不是有更好的方法来标记它?为什么777?
cell.textLabel.text = @"Limit passwords attempts";
UISwitch* actSwitch = (UISwitch*)[cell viewWithTag: SWITCH_TAG];
[actSwitch setTag: indexPath.section];
[actSwitch addTarget: self
action: @selector(actSwitchChanged:)
forControlEvents: UIControlEventValueChanged];
[actSwitch setOn:limit_password_attempts animated:YES];
我还有更多问题:我的程序现在运行良好,但是,我不明白改变了什么。我添加了更多方法:cellForType:
和cofigureCell:forIndexPath:
,但他们所做的一切在以前版本的cellForRowAtIndexPath:
中实际上都是相同的。
那么..这里改变了什么让它正常工作? :)