如何更新 UITable 中部分中动态变化的行数(及其单元格内容)?
我正在尝试创建一个 UITableViewController 子类,为我提供 UITableView 和我的应用程序设置。我在重新加载有关 UISwtitch 状态变化的数据时遇到问题。
该表有 3 个部分:
第 1 部分 - 连续一行
第 2 部分 - 第一行中的 UISwitch 使该部分由 1 或 3 组成 行(取决于状态 UI开关)
第 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 (例如)时,然后我希望我的第二部分再扩展 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 概念?但这里真的有必要有数据模型吗?为什么?如果是,那么我该怎么做?
感谢您的任何答复。 祝你有美好的一天。
它在我的代码中。我只是没有在我的问题中写下来。 reloadData 方法在 UISwtitch 切换后被调用:
[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 的内容,但它使其不是我期望的方式。
有什么想法吗?
I'm trying to make a UITableViewController subclass, providing me me UITableView with my app settings. I have a problem when reloading data on changing states of UISwtitch .
The table has 3 sections:
section 1 - one row constantly
section 2 - UISwitch in the first row
making this section consist of 1 or 3
rows (depending on the state of
UISwitch)section 3 - UISwitch in the first row
making this section consist of 1 or 3
rows (depending on the state of
UISwitch), but with another UISwitch
and additional rows data.
- (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;
}
}
Those two UISwitch-s in the firsts rows of second and third sections are changing BOOLs respectively
BOOL limit_password_attempts;
BOOL lock_when_inactive;
My problem is when i togle the UISwitch (for exmpl) in second section, then i expect my second section extend for 2 more rows, and be filled with new data. It extends, but new cells do not look like i want to. The second row becomes a copy of first row in the next section (a row with UISwitch for third section), and the third rows returns correcly in case if the third section was not extended before, and if it was, then this row becomes a copy of the second row from third section.
So my customising of cell looks like this, i guess the error is somewhere here.
- (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;
}
Looks like there is some hidden from me array with rows data, that is beeing filled onec, and table controller updates table in some way, depending on what row appeared, updating only them. Why does it makes copies, when adding row in a section. It's like an insterting a node in an array. I thought it has to push cells forward, but not just copy.
Have i to delete rows somehow to make this kind of table update?
I guess i'm missing some basic stuff here. Some MVC concept? But is it really necessary here to have a data model or not? Why? If yes, then how can i do it?
Thank you for any answers.
Have a good day.
It was in my code. I just didn't write it down in my question.
reloadData method is called after UISwtitch is toggled:
[pactSwitch setTag: indexPath.section];
[actSwitch addTarget: self
action: @selector(actSwitchChanged:)
forControlEvents: UIControlEventValueChanged];
In an actSwitchChanged method:
-(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];
}
So reloadData does change the viewTable's contents, but it makes it not the way i expect it to.
Any ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
数据模型始终存在......即使它只是 UITableView 调用的一堆 if 语句。我认为这种区别导致了问题。
您的布尔值代表您的基础数据模型。与数据模型的所有更改一样,您必须让表视图知道基础数据何时发生更改。
每当您更改布尔值之一时,请尝试添加以下调用。
A data model always exists... even if it's just a bunch of if statements your UITableView calls. I think this distinction is causing the problem.
Your booleans represent your underlying data model. Like all changes to data models, you have to let the table view know when your underlying data has been changed.
Try adding the following call whenever you change one of your booleans.
你是对的,你实现了错误的
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
。如果您正在寻找简单的方法来实现具有不同布局的单元格,而无需子类化UITableViewCell
那么您需要,例如:0) 阅读 this 用于深入理解 UITableView 编程
1) 为每个布局返回一种单元格类型的方法
2 ) 为每种类型返回一个单元格的方法
3) 使用路径配置单元格的方法
4) 最后一个方法的实现
You are right, You implemented the wrong of
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
. If you looking for easy way to implementation of the cells with different layouts without subclassing ofUITableViewCell
then you need, for your example:0) read this for deep understanding of UITableView programming
1) method wich returns a type of cell for each layout
2) method wich returns a cell for each type
3) method wich configure a cell with path
4) implementation of last method
加吉,谢谢你的回答。
它帮助了我,现在当我更改 UISwitch 条件时,表可以正确重新加载。
但我必须更改 uiswitch 的标签,因为我确实需要在
actSwitchChanged
方法中区分我正在处理的 UISwitch 类型,以了解它是limit_password_attempts
或lock_when_inactive
我想它将来不会引起问题?我的意思是,SWITCH_TAG 在这里被覆盖。
另外,为什么我需要
#define SWITCH_TAG 777
难道没有更好的方法来标记它吗?为什么是777?我还有更多问题:我的程序现在运行良好,但是,我不明白发生了什么变化。我添加了更多方法:
cellForType:
和cofigureCell:forIndexPath:
,但它们所做的一切实际上与之前版本的cellForRowAtIndexPath:
中的操作相同>。那么..这里做了什么改变才能使其正常工作? :)
Gaj, thanks for the answer.
It helped me, now table reloads correctly when i change UISwitch condition.
But i had to change a tag for uiswitch, becouse i do need to differ what kind of UISwitch i'm dealing with in the
actSwitchChanged
method, to understand either it islimit_password_attempts
orlock_when_inactive
I guess it will not couse a problem in future? I mean, that SWITCH_TAG is overwritten here.
And also, why do i need to
#define SWITCH_TAG 777
isn't there a better way to tag it? And why 777?And i have on more question: my program now works good, but, i dont understand what changed. I added to more methods:
cellForType:
andcofigureCell:forIndexPath:
, but all that they do was done practicaly the same in previous version ofcellForRowAtIndexPath:
.So .. what changed here to make it work correctly? :)