当单元格滚动回视图时表格崩溃

Posted

技术标签:

【中文标题】当单元格滚动回视图时表格崩溃【英文标题】:Table crashes when cell scrolls back into view 【发布时间】:2013-07-04 08:45:03 【问题描述】:

iPad:在单元格超出可见区域(屏幕高度)之前,我有一个表现良好的表格。当部分离开屏幕的最后一个单元格向下滚动以使其不再可见然后向上滚动时应用程序崩溃?为什么?

代码从运行良好的 iPhone 屏幕重新使用(它是一个通用应用程序)。被这个难住了

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

    static NSString *CellIdentifier = @"JobCell";

    UITableViewCell *cell;
    NSArray *versionCompatibility = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:@"."];

    if ( 6 <= [[versionCompatibility objectAtIndex:0] intValue] )
    
        // ios6 is installed
        cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    
    else
    
        // iOS5 is installed
        cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier ];
    


    // Configure the cell...
    Job *job = [self.jobs objectAtIndex:indexPath.row];

    NSLog(@"Dealing with cell %d",indexPath.row);

    UIColor *redcol = [UIColor colorWithRed:0.62745098039216 green:0.15294117647059 blue:0.15686274509804 alpha:1.0];

    NSString *jobString = job.jobAddress;
    jobString = [jobString stringByAppendingString:@", "];
    jobString = [jobString stringByAppendingString:job.jobPostcode];

    //cell.textLabel.text = jobString;

    NSLog(@"jobString %@",jobString);

    UILabel *jobLabel = (UILabel *)[cell.contentView viewWithTag:10];
    jobLabel.text = jobString;

    int jobsaved = job.jobSaved;

    if (jobsaved == 1)
    
        //cell.textLabel.textColor = redcol;
        jobLabel.textColor = redcol;
    
    else
    
        //cell.textLabel.textColor = [UIColor blackColor];
        jobLabel.textColor = [UIColor blackColor];
    

    NSLog(@"date %@",job.jobDate);

    UILabel *dateLabel = (UILabel *)[cell.contentView viewWithTag:11];

    if (! [job.jobDate isEqualToString:@""]) 


        NSDateFormatter *formater = [[NSDateFormatter alloc] init];
        [formater setDateFormat:@"yyyy-MM-dd"];

        NSDate *date2 = [formater dateFromString:job.jobDate];
        [formater setDateFormat:@"d MMM YYYY"];

        NSString *date = [formater stringFromDate:date2];

        //cell.detailTextLabel.text = date;
        dateLabel.text = date;

    
    else
    
        //cell.detailTextLabel.text = @"";
        dateLabel.text = @"";
    

    UIButton *mapBtn = (UIButton *)[cell viewWithTag:12];
    [mapBtn addTarget:self action:@selector(showMap:) forControlEvents:UIControlEventTouchUpInside];
    mapBtn.tag = indexPath.row;

    return cell;

错误是

 -[UIButton setText:]: unrecognized selector sent to instance 0x2aba90
2013-07-04 09:32:48.563 ESC GasCert[3175:707] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIButton setText:]: unrecognized selector sent to instance 0x2aba90'
*** First throw call stack:
(0x37e208bf 0x3796c1e5 0x37e23acb 0x37e22945 0x37d7d680 0x6e0e3 0x319289cb 0x31927aa9 0x31927233 0x318cbd4b 0x37d7f22b 0x37419381 0x37418f99 0x3741d11b 0x3741ce57 0x374446f1 0x374674c5 0x37467379 0x34b76f93 0x3764e891 0x37de9f43 0x37df4553 0x37df44f5 0x37df3343 0x37d764dd 0x37d763a5 0x37b4dfcd 0x318f6743 0x22f1 0x2278)
terminate called throwing an exception(lldb)

崩溃

0x217a:  blx    0xa7ef8                   ; symbol stub for: NSStringFromClass
0x217e:  mov    r7, r7
0x2180:  blx    0xa7f8c                   ; symbol stub for: objc_retainAutoreleasedReturnValue
0x2184:  movs   r2, #0
0x2186:  movt   r2, #0
0x218a:  ldr    r1, [sp, #8]
0x218c:  str    r0, [sp]
0x218e:  mov    r0, r1
0x2190:  ldr    r1, [sp, #4]
0x2192:  ldr    r3, [sp]
0x2194:  blx    0xa7ed8                   ; symbol stub for: UIApplicationMain
0x2198:  str    r0, [sp, #32]

我试过了

.h

@property (nonatomic, copy) NSString *jobString;

.m

_jobString = job.jobAddress;
_jobString = [_jobString stringByAppendingString:@", "];
_jobString = [_jobString stringByAppendingString:job.jobPostcode];

编辑:

这是不会崩溃的 iPhone 故事板代码

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

    static NSString *CellIdentifier = @"JobCell";

    UITableViewCell *cell;
    NSArray *versionCompatibility = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:@"."];

    if ( 6 <= [[versionCompatibility objectAtIndex:0] intValue] )
    
        // iOS6 is installed
        cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    
    else
    
        // iOS5 is installed
        cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier ];
    

    // Configure the cell...
    Job *job = [self.jobs objectAtIndex:indexPath.row];

    UIColor *redcol = [UIColor colorWithRed:0.62745098039216 green:0.15294117647059 blue:0.15686274509804 alpha:1.0];

    NSString *jobString = job.jobAddress;
    jobString = [jobString stringByAppendingString:@", "];
    jobString = [jobString stringByAppendingString:job.jobPostcode];    

    //cell.textLabel.text = jobString;

    UILabel *jobLabel = (UILabel *)[cell viewWithTag:10];
    jobLabel.text = jobString;

    int jobsaved = job.jobSaved;

    if (jobsaved == 1)
    
        //cell.textLabel.textColor = redcol;
        jobLabel.textColor = redcol;
    
    else
    
        //cell.textLabel.textColor = [UIColor blackColor];
        jobLabel.textColor = [UIColor blackColor];
    

    NSLog(@"date %@",job.jobDate);

    UILabel *dateLabel = (UILabel *)[cell viewWithTag:11];

    if (! [job.jobDate isEqualToString:@""]) 


        NSDateFormatter *formater = [[NSDateFormatter alloc] init];
        [formater setDateFormat:@"yyyy-MM-dd"];

        NSDate *date2 = [formater dateFromString:job.jobDate];
        [formater setDateFormat:@"d MMM YYYY"];

        NSString *date = [formater stringFromDate:date2];

        //cell.detailTextLabel.text = date;
        dateLabel.text = date;

    
    else
    
        //cell.detailTextLabel.text = @"";
        dateLabel.text = @"";
    

    UIButton *mapBtn = (UIButton *)[cell viewWithTag:12];
    [mapBtn addTarget:self action:@selector(showMap:) forControlEvents:UIControlEventTouchUpInside];
    mapBtn.tag = indexPath.row;

    return cell;

编辑:

决定整体使用标签方法充满了问题。使用本文中的解决方案解决了问题Detecting which UIButton was pressed in a UITableView

【问题讨论】:

与其使用标签来识别您的 UI 元素,不如使用自定义单元格并将元素作为单元格的属性来访问。 【参考方案1】:

我认为你弄乱了标签,这是我看到的:mapBtn.tag = indexPath.row; 你不应该像那样重写tag,因为UIButton 可能会被viewWithTag 而不是@987654325 检索@,这就是为什么你得到[UIButton setText:].

所以你应该找到另一种方式来标记动作。

【讨论】:

没错!使用标签的一个原因是需要小心谨慎。 好的...但是我在 iphone 故事板中使用完全相同的代码,它工作正常,滚动和所有?那么为什么只在 iPad 上崩溃呢? 可能是因为 indexPath 没有达到 12 ,所以列表中的元素可能较少。 查看UITableViewCell的文档。它的界面中有 UILabel *_textLabel 和 UILabel *_detailTextLabel。因此,您可以像 cell.textLabel.text = jobString 一样使用它,也可以根据需要使用 detailTextLabel。 @soryngod - 这是 uitablecell 中 uibutton 的标签,而不是 index.path【参考方案2】:

对于 iOS 5,您使用

cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

请注意,这将返回nil,因为您尚未使用标识符CellIdentifier 初始化任何单元格。虽然dequeueReusableCellWithIdentifier:forIndexPath: 总是返回一个有效的单元格,但对于dequeueReusableCellWithIdentifier:,您需要初始化该单元格(以防没有什么可以出队)。

因此,您将 nil 返回到 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath(在版本

这是documentation 段:

返回值

具有关联标识符的 UITableViewCell 对象,如果没有,则为 nil 此类对象存在于可重用单元队列中。

【讨论】:

不正确。如果正在使用情节提要,则根据需要创建单元格。这不是问题的提示是崩溃发生在滚动时,而不是在第一次创建单元格时。 soryngod 已经给出了正确答案 @Abizern 我不知道它在情节提要上是这样工作的,谢谢你的信息。

以上是关于当单元格滚动回视图时表格崩溃的主要内容,如果未能解决你的问题,请参考以下文章

滚动单元格时表格视图设置消失

滚动时隐藏自定义表格视图单元格标签如何解决?

带有自定义表格视图单元格的表格视图在滚动时消失

使用平移手势选择多个表格视图单元格

自动大小表格视图单元格扩展高度中的嵌套水平集合视图使集合视图滚动重置当重新加载单元格以累积行

滚动后表格视图单元格获取初始值