当我在iOS中滚动时,为什么UITable行每次都被取消选中

时间:2020-12-10 14:21:52

I have designed a Table view , For Select Followers list to send message, so there I can select some followers and then send them message on twitter.

我已经设计了一个Table视图,For Select Followers列表发送消息,所以我可以选择一些关注者,然后在twitter上发送消息。

I am using UITable View with UITableViewCellAccessoryCheckmark to make this.

我正在使用UITable View和UITableViewCellAccessoryCheckmark来实现这一点。

当我在iOS中滚动时,为什么UITable行每次都被取消选中

But when I scroll down table, the checked rows get unchecked every time.

但是当我向下滚动表格时,每次检查行都会被取消选中。

I have decleard table view and an array for selected followers in FollowersListView.h

我有一个十进制表视图和一个关于FollowersListView.h中选定关注者的数组

@interface FollowersListView : UIViewController<UITableViewDelegate,UITableViewDataSource>{

IBOutlet UITableView *tableFollowers;

NSMutableArray *listFollowrsName;   
NSMutableArray *listSelectedFollowrsId;
}

@property(nonatomic,retain) NSMutableArray *listFollowrsName;    
@property(nonatomic,retain) NSMutableArray *listSelectedFollowrsId;

@end

and my tableview code is like this in FollowersListView.m file

我的tableview代码在FollowersListView.m文件中是这样的

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{

    return [listFollowrsName count];
}



- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:@"CellWithSwitch"];
    //if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"CellWithSwitch"] autorelease];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    cell.textLabel.font = [UIFont systemFontOfSize:14];

    //cell.accessoryType = UITableViewCellAccessoryCheckmark;
    cell.accessoryType = UITableViewCellStyleDefault;
    //}

    NSString *cellValue = [listFollowrsName objectAtIndex:indexPath.row];
    cell.textLabel.text = cellValue;    

    return cell;
}

//to select a row
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)path {
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:path];


    if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
        cell.accessoryType = UITableViewCellAccessoryNone;        
        NSLog(@"row is un-checked %@",[NSNumber numberWithInt:path.row]);
        [listSelectedFollowrsId removeObject:[NSNumber numberWithInt:path.row]];
        NSLog(@"Now selected person are%@",listSelectedFollowrsId);

    } else {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
        NSLog(@"row is checked %@",[NSNumber numberWithInt:path.row]);
        [listSelectedFollowrsId addObject:[NSNumber numberWithInt:path.row]];       
        NSLog(@"Now selected person are%@",listSelectedFollowrsId);
    }

}

I guess I need to load every cell as per the already stored selected list but not getting how to do.

我想我需要根据已存储的选定列表加载每个单元格,但不知道如何操作。

Can anyone guide where I'm doing wrong, Any help would be appreciated

任何人都可以指导我做错的地方,任何帮助将不胜感激

Edit

@Novarg

I have declared "listSelectedFollowrsId" as a NSMutable Array in .h file and initialized in viewDidLoad method then adding/removing values in didSelectRowAtIndexPath method to manage selected rows.

我已将“listSelectedFollowrsId”声明为.h文件中的NSMutable数组,并在viewDidLoad方法中初始化,然后在didSelectRowAtIndexPath方法中添加/删除值以管理所选行。

4 个解决方案

#1


5  

The thing is that you create a new cell every time that you scroll. The if (cell == nil) condition must be there, otherwise you will just keep on re-writing the cell over and over again.

问题是每次滚动时都会创建一个新单元格。 if(cell == nil)条件必须在那里,否则你将继续一遍又一遍地重写单元格。

Try the following:

请尝试以下方法:

- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:@"CellWithSwitch"];
  if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"CellWithSwitch"] autorelease];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    cell.textLabel.font = [UIFont systemFontOfSize:14];
    cell.accessoryType = UITableViewCellStyleDefault;
  }
  NSString *cellValue = [listFollowrsName objectAtIndex:indexPath.row];
  cell.textLabel.text = cellValue;    
  return cell;
}

It might not work, I'm using a windows machine right now, so can't compile the code and test it myself now.

它可能无法正常工作,我现在正在使用Windows机器,因此无法编译代码并自行测试。

Hope it helps

希望能帮助到你

EDIT

If it doesn't solve the problem I'd also add a variable(probably an NSMutableDictionary) to keep a record of the names that have been "checked". Using that you can add the following just before return cell; in cellForRowAtIndexPath: method:

如果它没有解决问题,我还会添加一个变量(可能是NSMutableDictionary)来保存已经“检查”的名称的记录。使用它可以在返回单元格之前添加以下内容;在cellForRowAtIndexPath:方法:

if ([[theDictionary objectForKey:/*your key here, can be anything*/]isEqualToString:/*string or whatever, just make sure that the checked ones are different from the unchecked ones*/])
  cell.accessoryType = UITableViewCellAccessoryCheckmark;
else
  cell.accessoryType = UITableViewCellAccessoryNone;

EDIT 2

Here's what you should add right before return cell;(didn't see the listSelectedFollowrsId array before):

这是你应该在返回单元格之前添加的内容;(之前没有看到listSelectedFollowrsId数组):

cell.accessoryType = UITableViewCellAccessoryNone;
for (int i = 0; i < [listSelectedFollowrsId count]; i++) {
  if ([[listSelectedFollowrsId objectAtIndex:i]intValue] == indexPath.row) {
    cell.accessoryType = UITableViewCellAccessoryCheckmark;
  }
}

That will set the accessory to checkmark if the row has been previously tapped.

如果先前已经点过该行,则会将附件设置为复选标记。

#2


1  

you can use this:

你可以用这个:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath    
{       

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil)

    {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] autorelease];        
        cell.backgroundColor=[UIColor clearColor];        
        cell.selectionStyle=UITableViewCellSelectionStyleNone;      
        cell.accessoryType=UITableViewCellAccessoryNone;            
    }
    else
    {
        UIView *subview;
        while ((subview= [[[cell  contentView]subviews]lastObject])!=nil)       
            [subview removeFromSuperview];            
    }

    NSString *cellValue = [listFollowrsName objectAtIndex:indexPath.row];
    cell.textLabel.text = cellValue;    
    return cell;
}

#3


0  

Its because when you scroll the table, cellForRowAtIndexPath gets called.

这是因为当你滚动表时,会调用cellForRowAtIndexPath。

In this function you are creating the cell again and again. So, your checkmarks are getting removed which you have marked in didSelectRowAtIndexPath.

在此功能中,您将反复创建单元格。因此,您的检查标记将被删除,您已在didSelectRowAtIndexPath中标记。

Refer this link for detailed example of tableview.

有关tableview的详细示例,请参阅此链接。

#4


0  

In cellForRowAtIndexPath you are always setting it to unchecked. You need to test whether that row is in the your list of selected followers, if so set the accessory accordingly.

在cellForRowAtIndexPath中,您始终将其设置为未选中。您需要测试该行是否在您选择的关注者列表中,如果是这样,请相应地设置附件。

This is all due to cell reuse to keep memory consumption low even for tables with thousands of rows.

这完全归功于单元重用,即使对于具有数千行的表,也能保持较低的内存消耗。

#1


5  

The thing is that you create a new cell every time that you scroll. The if (cell == nil) condition must be there, otherwise you will just keep on re-writing the cell over and over again.

问题是每次滚动时都会创建一个新单元格。 if(cell == nil)条件必须在那里,否则你将继续一遍又一遍地重写单元格。

Try the following:

请尝试以下方法:

- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:@"CellWithSwitch"];
  if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"CellWithSwitch"] autorelease];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    cell.textLabel.font = [UIFont systemFontOfSize:14];
    cell.accessoryType = UITableViewCellStyleDefault;
  }
  NSString *cellValue = [listFollowrsName objectAtIndex:indexPath.row];
  cell.textLabel.text = cellValue;    
  return cell;
}

It might not work, I'm using a windows machine right now, so can't compile the code and test it myself now.

它可能无法正常工作,我现在正在使用Windows机器,因此无法编译代码并自行测试。

Hope it helps

希望能帮助到你

EDIT

If it doesn't solve the problem I'd also add a variable(probably an NSMutableDictionary) to keep a record of the names that have been "checked". Using that you can add the following just before return cell; in cellForRowAtIndexPath: method:

如果它没有解决问题,我还会添加一个变量(可能是NSMutableDictionary)来保存已经“检查”的名称的记录。使用它可以在返回单元格之前添加以下内容;在cellForRowAtIndexPath:方法:

if ([[theDictionary objectForKey:/*your key here, can be anything*/]isEqualToString:/*string or whatever, just make sure that the checked ones are different from the unchecked ones*/])
  cell.accessoryType = UITableViewCellAccessoryCheckmark;
else
  cell.accessoryType = UITableViewCellAccessoryNone;

EDIT 2

Here's what you should add right before return cell;(didn't see the listSelectedFollowrsId array before):

这是你应该在返回单元格之前添加的内容;(之前没有看到listSelectedFollowrsId数组):

cell.accessoryType = UITableViewCellAccessoryNone;
for (int i = 0; i < [listSelectedFollowrsId count]; i++) {
  if ([[listSelectedFollowrsId objectAtIndex:i]intValue] == indexPath.row) {
    cell.accessoryType = UITableViewCellAccessoryCheckmark;
  }
}

That will set the accessory to checkmark if the row has been previously tapped.

如果先前已经点过该行,则会将附件设置为复选标记。

#2


1  

you can use this:

你可以用这个:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath    
{       

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil)

    {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] autorelease];        
        cell.backgroundColor=[UIColor clearColor];        
        cell.selectionStyle=UITableViewCellSelectionStyleNone;      
        cell.accessoryType=UITableViewCellAccessoryNone;            
    }
    else
    {
        UIView *subview;
        while ((subview= [[[cell  contentView]subviews]lastObject])!=nil)       
            [subview removeFromSuperview];            
    }

    NSString *cellValue = [listFollowrsName objectAtIndex:indexPath.row];
    cell.textLabel.text = cellValue;    
    return cell;
}

#3


0  

Its because when you scroll the table, cellForRowAtIndexPath gets called.

这是因为当你滚动表时,会调用cellForRowAtIndexPath。

In this function you are creating the cell again and again. So, your checkmarks are getting removed which you have marked in didSelectRowAtIndexPath.

在此功能中,您将反复创建单元格。因此,您的检查标记将被删除,您已在didSelectRowAtIndexPath中标记。

Refer this link for detailed example of tableview.

有关tableview的详细示例,请参阅此链接。

#4


0  

In cellForRowAtIndexPath you are always setting it to unchecked. You need to test whether that row is in the your list of selected followers, if so set the accessory accordingly.

在cellForRowAtIndexPath中,您始终将其设置为未选中。您需要测试该行是否在您选择的关注者列表中,如果是这样,请相应地设置附件。

This is all due to cell reuse to keep memory consumption low even for tables with thousands of rows.

这完全归功于单元重用,即使对于具有数千行的表,也能保持较低的内存消耗。