xcode 向下滚动后,tableviews 单元格正在发生变化
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13877137/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
tableviews cells are changing after scrolling down
提问by Steaphann
I am making a form within a grouped tableview. In this form I have UIswitches and textfields. But after scrolling down, the cells styles are changing.
我正在分组的 tableview 中制作一个表单。在这种形式中,我有 UIswitches 和 textfields。但是向下滚动后,单元格样式正在发生变化。
Here is my cellForRowAtIndex
这是我的 cellForRowAtIndex
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;
static NSString *MyIdentifier = @"GenericCell";
cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] ;
}
NSString *text = nil;
if(indexPath.section == CREDENTIALS_SECTION){
if (indexPath.row == 0) {
NSLog(@"tot hier login");
UITextField *login = [[UITextField alloc] initWithFrame:CGRectMake(110, 10, 185, 30)];
login.adjustsFontSizeToFitWidth = YES;
login.placeholder = @"[email protected]";
login.keyboardType = UIKeyboardTypeEmailAddress;
login.returnKeyType = UIReturnKeyNext;
login.backgroundColor = [UIColor clearColor];
login.tag = 0;
login.delegate = self;
[login setEnabled: YES];
[cell addSubview:login];
}else if (indexPath.row == 1){
NSLog(@"tot hier pass");
UITextField *pass = [[UITextField alloc] initWithFrame:CGRectMake(110, 10, 185, 30)];
pass.adjustsFontSizeToFitWidth = YES;
pass.placeholder = @"Required";
pass.keyboardType = UIKeyboardTypeDefault;
pass.returnKeyType = UIReturnKeyDone;
pass.secureTextEntry = YES;
pass.backgroundColor = [UIColor clearColor];
pass.tag = 0;
pass.delegate = self;
[cell addSubview:pass];
}
if (indexPath.row == 0) { // Email
text = @"Email";
}
else if(indexPath.row == 1) {
text = @"Password";
}
}else if(indexPath.section == METHODS_SECTION){
UISwitch *toggleSwitch = [[UISwitch alloc]initWithFrame:CGRectMake(220, 10, 100, 30)];
toggleSwitch.tag = indexPath.row;
[toggleSwitch addTarget:self action:@selector(toggleSwitched:) forControlEvents:UIControlEventValueChanged];
[cell addSubview:toggleSwitch];
if (indexPath.row == 0) { // Web
text = @"Web applicatie";
}
else if(indexPath.row == 1) { //Mobile
text = @"Mobiele applicatie";
}
else if(indexPath.row == 2) { //Mail
text = @"E-mail";
}
}else if(indexPath.section == PHONE_SECTION){
UITextField *phoneText = [[UITextField alloc] initWithFrame:CGRectMake(20, 10, 185, 30)];
phoneText.adjustsFontSizeToFitWidth = YES;
phoneText.font = [UIFont fontWithName:@"Arial-BoldMT" size:18];
phoneText.keyboardType = UIKeyboardTypeNumberPad;
phoneText.delegate = self;
phoneText.textColor = [UIColor blackColor];
phoneText.text = _person.phone;
[cell addSubview:phoneText];
}else if(indexPath.section == REMARK_SECTION){
UITextView *textView = [[UITextView alloc]initWithFrame:CGRectMake(20, 10, 280, 260)];
textView.text = _person.remark;
textView.delegate = self;
textView.font = [UIFont fontWithName:@"Arial" size:15.0];
textView.backgroundColor = [UIColor clearColor];
[cell addSubview:textView];
text = @"";
}else if(indexPath.section == BUTTON_SECTION){
cell.backgroundColor = [UIColor redColor];
text = @"test";
}
cell.textLabel.text = text;
return cell;
}
After some searching I found that more people are having this problem. And that the problem lays in this piece of code.
经过一番搜索,我发现越来越多的人遇到了这个问题。问题出在这段代码中。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;
static NSString *MyIdentifier = @"GenericCell";
cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] ;
}
NSString *text = nil;
But I don't find a solution for it. Hope anybody can help!
但我没有找到解决方案。希望任何人都可以提供帮助!
Kind regards!
亲切的问候!
Clarification
澄清
Oké so here you see a screenshot of my form. below I have a red cell (save button) when I scroll down other cells are getting a red background. And some cells, text property's are changing.
好的,所以在这里您可以看到我的表单的屏幕截图。下面我有一个红色的单元格(保存按钮),当我向下滚动时,其他单元格获得红色背景。还有一些单元格,文本属性正在发生变化。
采纳答案by Hermann Klecker
That is not gong to work. Aparently you did not yet fully understand how the re-use mechanism works.
那不是锣工作。显然您还没有完全理解重用机制是如何工作的。
What do you do? First you fetch a cell to be re-used. If you get one -fine so far but the problem comes later. If you don't get one then you create a new one.
你做什么工作?首先,您获取要重新使用的单元格。如果到目前为止你得到了一个 - 罚款但问题稍后出现。如果你没有得到一个,那么你就创建一个新的。
When you have created a new one, which is the case at start before the user begins scrolling, then you add some UIItems depending on section and row. I will explain why this is not actually a smart thing to do.
当您创建了一个新的时,这是在用户开始滚动之前开始时的情况,然后您根据部分和行添加一些 UIItem。我将解释为什么这实际上不是一件明智的事情。
Then the user scrolls. Cells will dissappear from screen and then made available for re-use. Then you will fetch the cells for re-use. But it may well happen that those cells already have additional UI-Items on them because you have used them before in that way. In the following process you will add new UI Items regardless whether there are already additional UI-Items on that very cell.
然后用户滚动。细胞将从屏幕上消失,然后可供重复使用。然后您将获取单元格以供重复使用。但是很可能这些单元格上已经有额外的 UI 项,因为您以前以这种方式使用过它们。在以下过程中,您将添加新的 UI 项,而不管该单元格上是否已经存在其他 UI 项。
What can you do:
你能做什么:
Create your own custom table cell subclasses. One subclass for each set of additional ui items that you may need. That is probably the neatest way of doing it. For each subclass use a different re-use identifier (!!!) This is what I would recommend! However, there are alternatives:
You could still live with your concept but invent an individual type of re-use identfier for each type of cell that has some type of additional ui item on it. If so, then make sure that these UI items are only created and added as sub-views in the
if (cell == nil)
branch of your code. Only create them once and then re-use them. Cell reuse-IDs could be "email-display", "email-input" , "password-display", "password-input", "switch", ...A variance of the solution above would be, to calculate row and section into the reuse-identifier. Such as "cell-id-0.2" for section 0 and row 2 - or so. But still you will have to make sure that you really re-use the additional UI views and do not re-create them every time when the cell is filled with data. Plus, the layout in your first section varies depending on whether you want to input password and e-mail or just display them. You will still have to deal with those variations.
If cell == nil - meaning if a cell is re-used - then first clean it from every UI item that you may have added before. You can do that by tagging your UIViews with - let's say 99 - (anything different from 0 should do) upon creation and when reusing enumerate over all subviews and remove those, which have the tag 99. Despite that you can stick with the code that you have already made.
创建您自己的自定义表格单元子类。您可能需要的每组附加 ui 项目的一个子类。这可能是最简洁的方法。对于每个子类,使用不同的重用标识符 (!!!) 这就是我的建议!但是,还有其他选择:
你仍然可以接受你的概念,但为每种类型的单元格发明一种单独类型的重用标识符,上面有某种类型的附加 ui 项目。如果是这样,请确保这些 UI 项仅作为子视图创建和添加
if (cell == nil)
到您的代码分支中。只创建一次,然后重新使用它们。单元重用 ID 可以是 "email-display", "email-input" , "password-display", "password-input", "switch", ...上述解决方案的一个变化是,将行和节计算到重用标识符中。例如第 0 部分和第 2 行的“cell-id-0.2” - 左右。但是你仍然必须确保你真的重复使用额外的 UI 视图,并且不要在每次单元格填充数据时重新创建它们。另外,第一部分的布局取决于您是要输入密码和电子邮件还是仅显示它们。您仍然需要处理这些变化。
如果 cell == nil - 意味着如果一个单元格被重用 - 然后首先从您之前添加的每个 UI 项目中清除它。您可以通过在创建时使用 - 比方说 99 - (任何与 0 不同的都应该做)标记您的 UIViews 来做到这一点,并在重用所有子视图时枚举并删除那些具有标记 99 的子视图。尽管如此,您可以坚持使用代码你已经做了。
回答by Roland Keesom
The easiest fix is:
最简单的修复方法是:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"GenericCell"] ;
//some more code
return cell;
}
This would remove the reusability from the tableview, but since it's a limited settings view, it can be ok. I would still advice taking 1 or 2 from Hermann Klecker's solutions.
这将消除 tableview 的可重用性,但由于它是一个有限的设置视图,所以可以。我仍然建议从 Hermann Klecker 的解决方案中选择 1 或 2。
回答by iPhoneDeveloper
If you also need to persist UIControl state then use
如果您还需要保持 UIControl 状态,则使用
static NSString *MyIdentifier = [NSString stringWithFormat:@"GenericCell%d",indexPath.row];
It will always return your unique table row and you can use it as required.
它将始终返回您唯一的表格行,您可以根据需要使用它。
回答by Anusha Kottiyal
Try to remove all subviews from cell before reusing it. Try the code :
在重用之前尝试从单元格中删除所有子视图。试试代码:
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] ;
}
else
{
[cell.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
}
回答by Girish
Remove all subviews before adding the subviews on cell.
在单元格上添加子视图之前删除所有子视图。
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SimpleTableIdentifier]autorelease];
}
else
{
//To remove the subview of cell.
for (UIView *vwSubviews in [cell.contentView subviews])
{
[vwSubviews removeFromSuperview];
}
}
It may solves your problem.
它可能会解决您的问题。
回答by Mert
Actually you have some bad code here.
实际上你这里有一些不好的代码。
In the mehthod
在方法中
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
Unless it is not in if (cell == nil)
, you should NOT initialize and use any
除非它不在,否则if (cell == nil)
你不应该初始化和使用任何
-(void)addSubview:(UIView*)view
Why?
为什么?
The cells are views which are reused from tableview. So If you add some subview, next time while reusing the cell, it will be added more subviews on it. Simply they are overlapped and may cause MEMORY LEAK.
单元格是从 tableview 重用的视图。所以如果你添加一些子视图,下次在重用单元格时,它会在上面添加更多的子视图。只是它们重叠并可能导致内存泄漏。
Do not forget that cells are reusable. So;
不要忘记细胞是可重复使用的。所以;
if I have the following code unless I do not set text somewhere else. It is expected to all cells has the text in their text labels "this is a text". Because they are reusable.
如果我有以下代码,除非我不在其他地方设置文本。预计所有单元格的文本标签中都有文本“这是一个文本”。因为它们是可重复使用的。
if (someChangingBool) {
cell.textLabel.text = @"this is a text";
}
So I need to have an else for that if which sets the text something else.
所以我需要一个 else 来设置文本。
For more Information.
欲了解更多信息。