我有一个定制的UITableView单元格设置在我的UITableView像这样:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *identifier = @"CELL_IDENTIFIER"; SGCustomCell *cell = (SGCustomCell *)[tableView dequeueReusableCellWithIdentifier:identifier]; if (!cell) cell = [[SGCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]; cell = [self customizedCell:cell withPost:[postsArray objectAtIndex:indexPath.row]]; return cell; }
我设置了这样的单元格(具体设置UITextView.text为零 – 如this answer所述):
descriptionLabel.text = nil; descriptionLabel.text = post.postDescription; descriptionLabel.frame = CGRectMake(leftMargin - 4,currentTitleLabel.frame.origin.y + currentTitleLabel.frame.size.height + 10,self.frame.size.width - topMargin * 3,100); [descriptionLabel sizeToFit];
这些单元格是100%可重用的,UITextView是这样的(如你所见,没有什么特别的):
descriptionLabel = [[UITextView alloc] init]; descriptionLabel.font = [UIFont fontWithName:@"HelveticaNeue" size:11]; descriptionLabel.editable = NO; descriptionLabel.scrollEnabled = NO; descriptionLabel.dataDetectorTypes = UIDataDetectorTypeLink; descriptionLabel.frame = CGRectMake(leftMargin,10); [self addSubview:descriptionLabel];
但是当桌子有大约50个单元格,当我滚动它,我得到以下崩溃:
Terminating app due to uncaught exception 'NSRangeException',reason: 'NSMutableRLEArray objectAtIndex:effectiveRange:: Out of bounds'
这是绝对可笑的 – 我注释掉这一行 – descriptionLabel.dataDetectorTypes = UIDataDetectorTypeLink;并且应用程序停止崩溃!我花了几个小时试图弄清楚问题是什么,现在我只是得到这个.
在iOS 7.0.3上测试
解决方法
当具有数据类型的两个单元格正在出队时,发生崩溃
使用相同的单元格标识符.
这似乎是iOS中的一个bug,但是苹果可能有很好的理由来实现它.
(记忆聪明)
使用相同的单元格标识符.
这似乎是iOS中的一个bug,但是苹果可能有很好的理由来实现它.
(记忆聪明)
因此,唯一的100%防弹解决方案是为单元格提供唯一的标识符
包含数据类型.
这并不意味着您将为表格中的所有单元格设置唯一的标识符,当然,
因为它会吃掉太多的记忆,你的桌面滚动将会很慢.
您可以使用NSDataDetector来确定文本中是否找到匹配的类型,
然后只将发现的对象作为单元格标识符保存,如下所示:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSString *row = [self.dataSource objectAtIndex:indexPath.row]; static NSDataDetector *detector = nil; if (!detector) { NSError *error = NULL; detector = [[NSDataDetector alloc] initWithTypes:NSTextCheckingTypeLink | NSTextCheckingTypePhoneNumber error:&error]; } NSTextCheckingResult *firstDataType = [detector firstMatchInString:row options:0 range:NSMakeRange(0,[row length])]; NSString *dataTypeIdentifier = @"0"; if (firstDataType) { if (firstDataType.resultType == NSTextCheckingTypeLink) dataTypeIdentifier = [(NSURL *)[firstDataType URL] absoluteString]; else if (firstDataType.resultType == NSTextCheckingTypePhoneNumber) dataTypeIdentifier = [firstDataType phoneNumber]; } NSString *CellIdentifier = [NSString stringWithFormat:@"Cell_%@",dataTypeIdentifier]; UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; ...
注意:将NSDataDetector *检测器初始化为静态而不是初始化它为每个单元格提高性能.