我正在制作一个自定义的UITableView菜单选择器组件。每次我选择一个特定的行时,我都会保存这行的indexpath,所以下次当用户选择另一行时,人们就可以知道他之前选择的行了。所以我把它添加到了cellForRowAtIndexpath
中- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
cell.textLabel.text = self.left[indexPath.row][@"name"];
[tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:[[[NSUserDefaults standardUserDefaults] objectForKey:kPreviousSelectedRow] integerValue] inSection:0] animated:YES scrollPosition:UITableViewScrollPositionNone];
cell.selectionStyle = UITableViewCellSelectionStyleGray;
cell.textLabel.highlightedTextColor = [UIColor grayColor];
return cell;
}
当用户选择另一行时,将此行保存为:[[[NSUserDefaults standardUserDefaults] objectForKey:kPreviousSelectedRow],以便下次他可以看到他之前选择的行。
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:indexPath.row] forKey:kPreviousSelectedRow];
}
崩溃日志:index是[[[NSUserDefaults standardUserDefaults] objectForKey:kPreviousSelectedRow] integerValue],count是numberOfRows。正如你所看到的,它不应该超出范围。我不知道[0 ... 6]来自哪里。
2013-08-23 21:01:26.107 [17605:c07] index:10, count:14
2013-08-23 21:01:26.173[17605:c07] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 7 beyond bounds [0 .. 6]'
编辑:如果我慢慢滚动tableview,它不会崩溃,如果我快速滚动它,它会崩溃。什么?
答案 0 :(得分:2)
您遇到了崩溃,因为在这个确切的时间您没有指定索引的单元格,因为您只是在- (UITableViewCell*)tableView:cellForRowAtIndexPath:
为了获得您期望从selectRowAtIndexPath:
移出- (UITableViewCell*)tableView:cellForRowAtIndexPath:
的行为,并将其置于您正在更新UITableView
:-(void)viewDidLoad
或您调用的地方的其他方法中例如-(void)reloadTable
答案 1 :(得分:1)
您的应用正在崩溃,因为它正在尝试选择当前可能不可见的行。当数据可能尚未完全可用时,您尝试在数据源方法“cellForRowAtIndexPath”中选择一行。这就是你得到越界错误的原因。
对于您的具体示例,您可以尝试在更新值之前选择“didSelectRowAtIndexPath”中之前选择的行,因为您的数据已经显示,所以它不会崩溃。
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:[[[NSUserDefaults standardUserDefaults] objectForKey:kPreviousSelectedRow] integerValue] inSection:0] animated:YES scrollPosition:UITableViewScrollPositionNone];
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:indexPath.row] forKey:kPreviousSelectedRow];
}
答案 2 :(得分:1)
SVGreg是对的。您应该在另一个方法中使用单元格。但viewDidLoad不是最佳选择。您可以尝试这种有用的委托方法
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:[[[NSUserDefaults standardUserDefaults] objectForKey:kPreviousSelectedRow] integerValue] inSection:0] animated:YES scrollPosition:UITableViewScrollPositionNone];
cell.selectionStyle = UITableViewCellSelectionStyleGray;
}
答案 3 :(得分:0)
[tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:[[[NSUserDefaults standardUserDefaults] objectForKey:kPreviousSelectedRow] integerValue] inSection:0] animated:YES scrollPosition:UITableViewScrollPositionNone];
不应在cellForRowAtIndexpath
内。
从indexPath
获取didSelectRowAtIndexPath
,每次用户选择一个小区时都会触发该-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
。
如果要在用户取消选择单元格或选择其他单元格时触发另一种方法,请使用
{{1}}
答案 4 :(得分:0)
您可以创建一个容量等于行数的数组。用NO BOOL值(实际上是[NSnumber numberWithBool:]来填充它,因为它们需要是对象)。
然后在
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
更改位置indexPath.row,
处对象的值并在
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
检查数组中的BOOL值是否设置为YES然后选择单元格。 (cell.selected = YES)
您可以加倍努力,使用自定义选择样式制作自定义单元格,然后在单元格上创建一个方法,该方法将应用您选择的设计并在cellForRowAtIndexPath中调用该方法。
答案 5 :(得分:0)
哦,我只是将selectRowAtindex替换为layoutsubview,现在它不会崩溃。感谢SVGreg的提示。