从 UITableView 中删除多个选择在滚动后抛出异常(重用问题?)
Deleting multiple selections from UITableView throws exception after scrolling (reuse issue?)
我正在尝试从 table 视图中删除多个 selection。一切正常,直到我向上或向下滚动,然后它崩溃并抛出异常。
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
对象不能为nil
这就是我删除对象的方式:
- (IBAction)deleteObjects:(id)sender {
NSArray *selectedRows = [self.tableView indexPathsForSelectedRows];
BOOL deleteSpecificRows = selectedRows.count > 0;
if (deleteSpecificRows)
{
NSMutableArray *stringsOfObjects = [NSMutableArray new];
for (NSIndexPath *selectionIndex in selectedRows) {
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:selectionIndex];
[stringsOfObjects addObject:cell.textLabel.text];
}
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [paths objectAtIndex:0];
NSString *plistPath = [path stringByAppendingPathComponent:@"AlertSubscriptions.plist"];
NSMutableArray *array = [[[NSMutableArray alloc] initWithContentsOfFile:plistPath] mutableCopy];
[array removeObjectsInArray:stringsOfObjects];
[self.alertSubArray removeObjectsInArray:stringsOfObjects];
[array writeToFile:plistPath atomically:YES];
[self.tableView deleteRowsAtIndexPaths:selectedRows withRowAnimation:UITableViewRowAnimationAutomatic];
}
再次一切正常,除非我滚动 up/down 到 select/deselect 更多单元格所以我将我的单元格子类化,因为我读到不会在 SO 上重用单元格。
供参考:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
SubscriptionsTableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:nil];
if (cell == nil) {
cell = [[SubscriptionsTableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:nil];
}
cell.textLabel.text = [self.alertSubArray objectAtIndex:indexPath.row];
cell.textLabel.textAlignment = NSTextAlignmentLeft;
return cell;
}
我试过有没有静态单元格。我试过将 dequeueReusableCellWithIdentifier 设置为静态单元格,但没有。滚动时都不起作用
static NSString *CellIdentifier = @"Cell";
错误日志:
2015-06-28 15:46:19.379 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
*** First throw call stack:
(0x186d3c2d8 0x1985680e4 0x186c234c0 0x10017e7d8 0x18b7b1404 0x18b79a4e0 0x18b7b0da0 0x18b7b0a2c 0x18b7a9f68 0x18b77d18c 0x18ba1e324 0x18b77b6a0 0x186cf4240 0x186cf34e4 0x186cf1594 0x186c1d2d4 0x1904336fc 0x18b7e2fac 0x1001646d4 0x198be6a08)
libc++abi.dylib: terminating with uncaught exception of type NSException
编辑
因此,在尝试了其他人告诉我要做的事情之后,我做了以下事情:
设置异常断点。崩溃后填充的行是 [stringsOfObjects addObject:cell.textLabel.text];
行。
我已经确保我的 cellForRowAtIndexPath
方法设置正确:
}
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell.backgroundColor = [UIColor whiteColor];
[self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleSingleLine];
[self.tableView setRowHeight:45];
cell.textLabel.text = [self.alertSubArray objectAtIndex:indexPath.row];
cell.textLabel.textAlignment = NSTextAlignmentLeft;
return cell;
}
在那之后,我在将对象添加到 NSMutableArray 时仍然遇到崩溃,所以我查看了调试器并确保我的 UITableViewCell 不像我提到的 Robot 那样是 nil,它看起来像是的,但我不知道从这里去哪里:因为在我看来它不是 nil
如您所见,我 select 编辑了 6 行,但它只添加了 2 个对象。我不知道为什么这如此困难,为什么有些不是时却为零?为什么我可以完全删除它们而无需滚动到 select 更多?
因此,在评论中进行了广泛讨论之后,问题似乎如下:
deleteObjects:
方法中[stringsOfObjects addObject:cell.textLabel.text];
的逻辑是错误的。这是因为它直接从单元格而不是填充单元格的数组后备存储中获取文本。
单元格可以滚动到屏幕外并重新使用,因此其中的文本不再正确,事实上,单元格不再 "exists" 因为它已被重新使用。如果单元格不是 "exist",将在文本字段可能是 nil
的位置创建一个空单元格。请注意,细胞重复使用是一件好事;不要创建单元格,也不要重复使用它们,否则你会 运行 很快内存不足。
相反,从填充单元格本身的后备存储中获取文本,而不是直接从单元格中获取文本。我希望代码是这样的:
[stringsOfObjects addObject:[self.alertSubArray objectAtIndex:selectionIndex.row]];
我正在尝试从 table 视图中删除多个 selection。一切正常,直到我向上或向下滚动,然后它崩溃并抛出异常。
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
对象不能为nil
这就是我删除对象的方式:
- (IBAction)deleteObjects:(id)sender {
NSArray *selectedRows = [self.tableView indexPathsForSelectedRows];
BOOL deleteSpecificRows = selectedRows.count > 0;
if (deleteSpecificRows)
{
NSMutableArray *stringsOfObjects = [NSMutableArray new];
for (NSIndexPath *selectionIndex in selectedRows) {
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:selectionIndex];
[stringsOfObjects addObject:cell.textLabel.text];
}
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [paths objectAtIndex:0];
NSString *plistPath = [path stringByAppendingPathComponent:@"AlertSubscriptions.plist"];
NSMutableArray *array = [[[NSMutableArray alloc] initWithContentsOfFile:plistPath] mutableCopy];
[array removeObjectsInArray:stringsOfObjects];
[self.alertSubArray removeObjectsInArray:stringsOfObjects];
[array writeToFile:plistPath atomically:YES];
[self.tableView deleteRowsAtIndexPaths:selectedRows withRowAnimation:UITableViewRowAnimationAutomatic];
}
再次一切正常,除非我滚动 up/down 到 select/deselect 更多单元格所以我将我的单元格子类化,因为我读到不会在 SO 上重用单元格。
供参考:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
SubscriptionsTableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:nil];
if (cell == nil) {
cell = [[SubscriptionsTableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:nil];
}
cell.textLabel.text = [self.alertSubArray objectAtIndex:indexPath.row];
cell.textLabel.textAlignment = NSTextAlignmentLeft;
return cell;
}
我试过有没有静态单元格。我试过将 dequeueReusableCellWithIdentifier 设置为静态单元格,但没有。滚动时都不起作用
static NSString *CellIdentifier = @"Cell";
错误日志:
2015-06-28 15:46:19.379 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
*** First throw call stack:
(0x186d3c2d8 0x1985680e4 0x186c234c0 0x10017e7d8 0x18b7b1404 0x18b79a4e0 0x18b7b0da0 0x18b7b0a2c 0x18b7a9f68 0x18b77d18c 0x18ba1e324 0x18b77b6a0 0x186cf4240 0x186cf34e4 0x186cf1594 0x186c1d2d4 0x1904336fc 0x18b7e2fac 0x1001646d4 0x198be6a08)
libc++abi.dylib: terminating with uncaught exception of type NSException
编辑 因此,在尝试了其他人告诉我要做的事情之后,我做了以下事情:
设置异常断点。崩溃后填充的行是 [stringsOfObjects addObject:cell.textLabel.text];
行。
我已经确保我的 cellForRowAtIndexPath
方法设置正确:
}
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell.backgroundColor = [UIColor whiteColor];
[self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleSingleLine];
[self.tableView setRowHeight:45];
cell.textLabel.text = [self.alertSubArray objectAtIndex:indexPath.row];
cell.textLabel.textAlignment = NSTextAlignmentLeft;
return cell;
}
在那之后,我在将对象添加到 NSMutableArray 时仍然遇到崩溃,所以我查看了调试器并确保我的 UITableViewCell 不像我提到的 Robot 那样是 nil,它看起来像是的,但我不知道从这里去哪里:因为在我看来它不是 nil
如您所见,我 select 编辑了 6 行,但它只添加了 2 个对象。我不知道为什么这如此困难,为什么有些不是时却为零?为什么我可以完全删除它们而无需滚动到 select 更多?
因此,在评论中进行了广泛讨论之后,问题似乎如下:
deleteObjects:
方法中[stringsOfObjects addObject:cell.textLabel.text];
的逻辑是错误的。这是因为它直接从单元格而不是填充单元格的数组后备存储中获取文本。
单元格可以滚动到屏幕外并重新使用,因此其中的文本不再正确,事实上,单元格不再 "exists" 因为它已被重新使用。如果单元格不是 "exist",将在文本字段可能是 nil
的位置创建一个空单元格。请注意,细胞重复使用是一件好事;不要创建单元格,也不要重复使用它们,否则你会 运行 很快内存不足。
相反,从填充单元格本身的后备存储中获取文本,而不是直接从单元格中获取文本。我希望代码是这样的:
[stringsOfObjects addObject:[self.alertSubArray objectAtIndex:selectionIndex.row]];