English 中文(简体)
Crash on UITable 最后一行移至最后一行时的情况
原标题:Crash on UITableView endUpdates when moving last row in section

我有一架可调频的书记员,由一名NSFettorResultsController提供支持。

我的NSFetResultsController将成果分成两部分,以资养。

In a background thread, the datasource is altered such that rows are added or removed. I have my background thread s NSManagedObjectContext s merging correctly and this situation work fine for most cases. Rows alter when the data is changed and move between sections with animations.

There is one situation however where my application crashes with an EXC_BAD_ACCESS. The case is when the last row in a section is moved to the other section. (Stack trace below). The crash occurs in objc_msgSend but the normal debugging tips I use aren t returning anything helpful, I simply receive "Value can t be converted to integer" from gdb.

部队指挥官 代表方法按以下顺序排列:

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller;
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type;
     // ^ The parameters specify a deletion of the 1st section
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath;
     // ^ The parameters specify a moved row from the 1st section to the 1st section 
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller;

通过StackOverflow,许多遇到类似问题的人正在使用国家航空航天局或国家航空航天局人工支持其UITableViewController,他们只是在正确的时候不更新数据来源。 在此情况下,国家邮政和电信局的主计长正在处理收复行和分行数目的问题,并在打电话到<密码>时明确更新。

Has anyone got any debugging tips, pointers or solutions? This blog post hints at working around a similar problem where a new section is created.

如果我无法解决这个问题,我有两个选择:

  1. Forgo animation on rows and simply call [tableView reloadData]
  2. Switch to using NSArray backed storage for the UITableView and hope for the best

Update

I have modified the Apple sample Core Data application "Locations" to use an NSFetchedResultsController directly and reproduced the issue. I have uploaded the source code for this project. Use that project to reproduce the issue.

  1. Simply click the + button a few times and wait
  2. Every 5 seconds an item gets moved to another category.
  3. When the first category is about to be emptied, it crashes.

坠毁有时是为了为同一囚室制造两张动画,而就这个专题而言,其他SackOverflow问题也是如此。 更常见的情况是上文和下文所讨论的。

Reference

st痕:

#0  0x31e0afbc in objc_msgSend ()
#1  0x32c11522 in -[_UITableViewUpdateSupport(Private) _computeRowUpdates] ()
#2  0x32c10510 in -[_UITableViewUpdateSupport initWithTableView:updateItems:oldRowData:newRowData:oldRowRange:newRowRange:context:] ()
#3  0x32c0f99e in -[UITableView(_UITableViewPrivate) _endCellAnimationsWithContext:] ()
#4  0x32c0e66c in -[UITableView endUpdatesWithContext:] ()
#5  0x000088d6 in -[DraftHistoryController controllerDidChangeContent:] (self=0x3f6f1e0, _cmd=0x377ca29c, controller=0x3f716e0) at /Users/ataylor/Documents/Documents/Programming/iPhone/Drafter/Drafter/Drafter/DraftHistoryController.m:323
#6  0x3775a892 in -[NSFetchedResultsController(PrivateMethods) _managedObjectContextDidChange:] ()

主计长 代表方法与 Apple果样本法相同:

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
    // The fetch controller is about to start sending change notifications, so prepare the table view for updates.
    [self.tableView beginUpdates];
}


- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {

    UITableView *tableView = self.tableView;

    switch(type) {

        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeUpdate:
            [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            break;

        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            // Reloading the section inserts a new row and ensures that titles are updated appropriately.
            [tableView reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}


- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {

    switch(type) {

        case NSFetchedResultsChangeInsert:
            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    // The fetch controller has sent all current change notifications, so tell the table view to process all updates.
    [self.tableView endUpdates];     // <---- Crash occurs here
}

相关可上诉的意见 代表方法如下:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return [[self.fetchedResultsController sections] count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
    return [sectionInfo numberOfObjects];
}
最佳回答

我进行了快速研究。 您经过修改的定位项目在我身上打了车,但确实产生了核心数据例外。 问题在于重载控制器:didChange 反对: 我对法典作了如下修改,对我(包括标题)关于OS4.3和OS 5的 everything。

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
    UITableView *tableView = self.tableView;

    switch(type) {

        // other cases here

        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}
问题回答

我很奇怪的是,这部法典把一个问题固定下来,增加了一个新部分,因此我决定把它搁置起来,取代我目前的全国家庭福利基金。 主计长 代表方法确实解决了我的问题。 我通过引人道,发现这部 Apple果的“Locations”样本在使用NSFetlateResults时坠毁。 主计长:

    case NSFetchedResultsChangeMove:
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        // Reloading the section inserts a new row and ensures that titles are updated appropriately.
        [tableView reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
        break;

但以下法典完美运作:

    case NSFetchedResultsChangeMove:
        if (newIndexPath != nil) {
            [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            [self.tableView insertRowsAtIndexPaths: [NSArray arrayWithObject:newIndexPath] withRowAnimation: UITableViewRowAnimationTop];
        }
        else {
            [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:[indexPath section]] withRowAnimation:UITableViewRowAnimationFade];
        }
        break;

我没有一例会标题会改变,我却在继续拼凑,以解决问题 Apple果的代码,其意图是围绕章节标题确定。

由于每一个问题都需要迅速回答,这里的答案(基于XJones的接受回答)。 如同其他答复一样,魔法在Move:删除并插入,而不是流。

这是我的挪威人民民主阵线代表。

func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
    switch type {
    case .Delete:
        if let deletePath = indexPath {
            self.tableView.deleteRowsAtIndexPaths([deletePath], withRowAnimation: .None)
        }
        break
    case .Insert:
        if let insertPath = newIndexPath {
            self.tableView.insertRowsAtIndexPaths([insertPath], withRowAnimation: .Fade)
        }
        break
    case .Update:
        if let updatePath = indexPath {
            self.tableView.reloadRowsAtIndexPaths([updatePath], withRowAnimation: .None)
        }
        break
    case .Move:
        if let indexPath = indexPath, newIndexPath = newIndexPath {
            self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
            self.tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Fade)
        }
        break
    }
}

我正忙于把最后一行删除一栏。

确保你执行<斯特隆>控制器:didChange Section:atIndex:forChangeType:,处理解职问题。

- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
           atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {

    switch(type) {
        case NSFetchedResultsChangeInsert:
            [self.viewTable insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
                          withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [self.viewTable deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
                          withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}




相关问题
List Contents of Directory in a UITableView

I am trying to list the contents of Ringtones directory in a TableView, however, I am only getting the last file in the directory in ALL cells, instead of file per cell. This is my code: - (...

iPhone NSUserDefaults persistance difficulty

In my app i have a bunch of data i store in the NSUserdefaults. This information consists of an NSObject (Object1) with NSStrings and NSNumbers and also 2 instances of yet another object (Object2). ...

Writing a masked image to disk as a PNG file

Basically I m downloading images off of a webserver and then caching them to the disk, but before I do so I want to mask them. I m using the masking code everyone seems to point at which can be found ...

Resize UIImage with aspect ratio?

I m using this code to resize an image on the iPhone: CGRect screenRect = CGRectMake(0, 0, 320.0, 480.0); UIGraphicsBeginImageContext(screenRect.size); [value drawInRect:screenRect blendMode:...

Allowing interaction with a UIView under another UIView

Is there a simple way of allowing interaction with a button in a UIView that lies under another UIView - where there are no actual objects from the top UIView on top of the button? For instance, ...

热门标签