iOS - [UITableView reloadData] 重新加载,但不删除旧单元格?
Posted
技术标签:
【中文标题】iOS - [UITableView reloadData] 重新加载,但不删除旧单元格?【英文标题】:iOS - [UITableView reloadData] reloads, but not removes old cells? 【发布时间】:2014-03-05 21:49:37 【问题描述】:这很奇怪,我知道,但我的 [UITableView reloadData] 没有删除旧单元格,如下所示:
你看到的混乱发生在我点击+按钮后,回来并再次更改值。加号按钮将 navigationController 推到另一个控制器上,当我点击 back 按钮 回来并更改了值后,这就是我所看到的。这怎么可能??我使用了一个自定义视图(从 UIView 子类化),它是作为带有 UILabel 的 UIStepper 创建的。这是自定义 UIView 的代码、controller.m 和 .h-.m 文件。
controller.m
@interface ViewController ()
@property NSString *docsDir;
@property sqlite3 *DB;
@property NSArray *dirPaths;
@property NSString* databasePath;
@property (strong, nonatomic) IBOutlet UITableView *tableView;
@property BOOL isCreatedBefore;
@property NSArray *theList;
@end
@implementation ViewController
@synthesize docsDir;
@synthesize DB;
@synthesize dirPaths;
@synthesize databasePath;
- (void)viewDidLoad
[super viewDidLoad];
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent: [NSString stringWithFormat:@"database.db"]]];
[self createDatabase];
self.theList = [self readAllEntries];
-(void) viewWillAppear:(BOOL)animated
self.theList = [self readAllEntries];
[self.tableView reloadData];
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
return 1;
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
return [self.theList count];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
SeriesObject * obj = [self.theList objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cellocan"];
UILabel *nameLabel = (UILabel *)[cell.contentView viewWithTag:1];
[nameLabel setText:obj.name];
CounterView *seasonCounter = [[CounterView alloc] initWithX:220 WithY:28 WithName:obj.name withCount:obj.session withCustomTag:indexPath.row];
seasonCounter.tag = 2;
CounterView *episodeCounter = [[CounterView alloc] initWithX:268 WithY:28 WithName:obj.name withCount:obj.episode withCustomTag:indexPath.row];
episodeCounter.tag = 4;
[cell.contentView addSubview:seasonCounter];
[cell.contentView addSubview:episodeCounter];
return cell;
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
// Return YES if you want the specified item to be editable.
return YES;
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
if (editingStyle == UITableViewCellEditingStyleDelete)
SeriesObject *obj = [self.theList objectAtIndex:indexPath.row];
[self deleteEntryWithID:obj.idd];
self.theList = [self readAllEntries];
[self.tableView reloadData];
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
return 88;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
[tableView deselectRowAtIndexPath:indexPath animated:YES];
______and more about reading from database or deleting; not about the view. (this is a very simple app, as a free time hobby; so I didn't spend time to follow MVC)
CounterView.h
@interface CounterView : UIView
@property NSString* name;
@property NSInteger count;
@property UILabel *label;
@property NSInteger customTag;
- (id)initWithX:(CGFloat)xPoint WithY:(CGFloat)yPoint WithName:(NSString*)newName withCount:(NSInteger)newCount withCustomTag:(NSInteger)newTag;
@end
CounterView.m
@interface CounterView()
@property NSString *docsDir;
@property sqlite3 *DB;
@property NSArray *dirPaths;
@property NSString* databasePath;
@end
@implementation CounterView
@synthesize docsDir;
@synthesize DB;
@synthesize dirPaths;
@synthesize databasePath;
- (id)initWithX:(CGFloat)xPoint WithY:(CGFloat)yPoint WithName:(NSString*)newName withCount:(NSInteger)newCount withCustomTag:(NSInteger)newTag
self = [super initWithFrame:CGRectMake(xPoint, yPoint, 24, 52)];
if (self)
self.customTag = newTag;
self.count = newCount;
self.name = newName;
UIButton *btnUp = [[UIButton alloc] initWithFrame:CGRectMake(3, 2, 18, 12)];
[btnUp setImage:[UIImage imageNamed:@"top.png"] forState:UIControlStateNormal];
[btnUp addTarget:self action:@selector(increaseValue) forControlEvents:UIControlEventTouchUpInside];
UIButton *btnDown = [[UIButton alloc] initWithFrame:CGRectMake(3, 38, 18, 12)];
[btnDown setImage:[UIImage imageNamed:@"bottom.png"] forState:UIControlStateNormal];
[btnDown addTarget:self action:@selector(decreaseValue) forControlEvents:UIControlEventTouchUpInside];
self.label = [[UILabel alloc] initWithFrame:CGRectMake(0, 14, 24, 24)];
[self.label setText:[NSString stringWithFormat:@"%ld", (long)self.count]];
self.label.textAlignment = NSTextAlignmentCenter;
[self addSubview:btnUp];
[self addSubview:btnDown];
[self addSubview:self.label];
return self;
- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents
-(void) increaseValue
self.count++;
[self.label setText:[NSString stringWithFormat:@"%ld", (long)self.count]];
-(void) decreaseValue
self.count--;
[self.label setText:[NSString stringWithFormat:@"%ld", (long)self.count]];
____and some more database codes too..
【问题讨论】:
【参考方案1】:在您的cellForRowAtIndexPath:
中,您每次都添加一个子视图。 UITableView 重用单元格,因此当您重新加载时,您会得到一个“脏”单元格。您需要检查视图是否已经存在。如果是这样,请修改视图而不是添加视图。谷歌“UITableViewCell viewWithTag”查看一些示例代码。
【讨论】:
我以前用过。所以每次都会发生,但由于内容稳定,我从来没有意识到。谢谢.. @Esq 模式已经写了几百遍了,很容易找到。【参考方案2】:- (void)prepareForReuse
//remove your subviews here
[self.subViewToRemove removeFromSuperView];
【讨论】:
【参考方案3】:我建议您创建一个从 UITableViewCell 派生的自定义单元格类,并让它包含您的自定义 CounterView 实例。在这种情况下,您不需要每次都在 cellForRowAtIndexPath
中添加子视图(这会导致您遇到问题),而是可以传递它所需的任何值。
【讨论】:
【参考方案4】:经过一些修改,在 cellForRowAtIndexpath: 方法中使用它解决了所有问题。谢谢大家。
if (cell != nil)
NSArray* subviews = [cell.contentView subviews];
for (UIView* view in subviews)
[view removeFromSuperview];
【讨论】:
这将在紧要关头起作用,但是如果您的单元格变得复杂,这种方法会使您的滚动感觉不稳定。重用视图比删除和添加视图要快。以上是关于iOS - [UITableView reloadData] 重新加载,但不删除旧单元格?的主要内容,如果未能解决你的问题,请参考以下文章
iOS - [UITableView reloadData] 重新加载,但不删除旧单元格?