菜鸟教程小白 发表于 2022-12-13 06:40:03

iphone - NSFetchedResultsController 和插入记录的问题


                                            <p><p>好的,这个让我发疯了,我已经尝试了所有可以在互联网上找到的可能的解决方案,但仍然没有。所以这是我的情况:
我有一个 View ,上面有一个按钮。当它被触摸时,它会弹出一个客户列表供用户选择。当他们选择它时,我使用 fetchedresultscontroller 来获取与客户关联的部件并将它们显示在 tableview 中。这一切都很好。问题是如果我选择了客户 A 并插入一个新部件,然后转到客户 B 并插入一个新部件,当我重新选择客户 A 并尝试插入另一个部件时,应用程序崩溃并出现以下错误:</p>

<blockquote>
<p><strong>* Assertion failure in -, /SourceCache/UIKit_Sim/UIKit-1447.6.4/UITableView.m:976
2011-02-21 10:39:12.896
SalesPro Serious
application error.An exception was
caught from the delegate of
NSFetchedResultsController during a
call to -controllerDidChangeContent:.
Invalid update: invalid number of rows
in section 0.The number of rows
contained in an existing section after
the update (1) must be equal to the
number of rows contained in that
section before the update (1), plus or
minus the number of rows inserted or
deleted from that section (1 inserted,
0 deleted). with userInfo (null)
2011-02-21 10:39:12.907
SalesPro *</strong> Terminating
app due to uncaught exception
&#39;NSRangeException&#39;, reason:
&#39;-[UITableView
scrollToRowAtIndexPath:atScrollPosition:animated:]:
row (1) beyond bounds (1) for section
(0).&#39;</p>
</blockquote>

<p><strong>处理客户选择的代码</strong></p>

<pre><code>-(void) CustomerSelectedRaised:(NSNotification *)notif
{
    NSLog(@&#34;Received Notification - Customer Selected&#34;);
    selectedCustomer = (Customer *);
    ;
    if (popoverController != nil) {
      ;
    }

    fetchedResultsController = nil;

    NSError *error;
    if (![ performFetch:&amp;error]) {
      //Update to handle error appropriately
      NSLog(@&#34;Unresolved error %@, %@&#34;, error, );
      exit(-1); //fail
    }

    ;
}
</code></pre>

<p><strong>FetchedResultsController 代码</strong></p>

<pre><code>#pragma mark -
#pragma mark Fetch results controller

- (NSFetchedResultsController *)fetchedResultsController {
    if (fetchedResultsController != nil) {
      return fetchedResultsController;
    }

    //set-up fetched results controller
    NSFetchRequest *fetchRequest = [ init];
    NSEntityDescription *entity = ;
    ;
    ;
    NSLog(@&#34;TAMS ID: %@&#34;, selectedCustomer.customerTAMSID);
    ];

    //set to sort by customer name
    NSSortDescriptor *sortDescriptor = [ initWithKey:@&#34;sortOrder&#34; ascending:YES];
    NSArray *sortDescriptors = [ initWithObjects:sortDescriptor, nil];   
    ;

    NSFetchedResultsController *aFetchedResultsController = [
                                                             initWithFetchRequest:fetchRequest
                                                             managedObjectContext:
                                                             sectionNameKeyPath:nil cacheName:nil];
    ;
    ;

    //clean-up
    ;
    ;
    ;
    ;

    //return results
    return fetchedResultsController;
}

- (void)controllerWillChangeContent:(NSFetchedResultsController*)controller
{
    [ beginUpdates];
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    // In the simplest, most efficient, case, reload the table view.
    [ endUpdates];
}

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

    UITableView *tableView = self.partsListGrid;

    switch(type) {

      case NSFetchedResultsChangeInsert:
             withRowAnimation:UITableViewRowAnimationFade];
            break;

      case NSFetchedResultsChangeDelete:
             withRowAnimation:UITableViewRowAnimationFade];
            break;

      case NSFetchedResultsChangeUpdate:
             atIndexPath:indexPath withHeight:tableView.rowHeight];
            break;

      case NSFetchedResultsChangeMove:
             withRowAnimation:UITableViewRowAnimationFade];
            withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}

- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id &lt;NSFetchedResultsSectionInfo&gt;)sectionInfo
         atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {

    switch(type) {
      case NSFetchedResultsChangeInsert:
             withRowAnimation:UITableViewRowAnimationFade];
            break;
      case NSFetchedResultsChangeDelete:
             withRowAnimation:UITableViewRowAnimationFade];
            break;
      case NSFetchedResultsChangeMove:
            break;
      case NSFetchedResultsChangeUpdate:
            break;
      default:
            break;
    }
}
</code></pre>

<p><strong>添加零件代码</strong></p>

<pre><code>-(void) addScannedPart:(Part *)part
{
    // Check to see if entered part is already in list
    NSFetchRequest *fetchRequest = [ init];
    NSEntityDescription *partsEntity = ;
    ;

    NSPredicate *predicate = ;
    ;

    NSError *error = nil;
    NSArray *fetchedParts = ;

    if ( == 0) {
      //Create a new instance of the entity managed object by the fetched results controller
      NSManagedObjectContext *context = ;
      NSEntityDescription *entity = [ entity];

      NSLog(@&#34;Entity Name: %@&#34;, );

      NSManagedObject *newManagedObject = inManagedObjectContext:context];

      //Add fields to Managed Object
      int sortOrder = [ count];
      sortOrder++;

       forKey:@&#34;lineAbbreviation&#34;];
       forKey:@&#34;partNumber&#34;];
       intValue]] forKey:@&#34;orderQuantity&#34;];
      ;
       forKey:@&#34;sortOrder&#34;];

      //Save the context
      NSError *error = nil;
      if (!) {
            NSLog(@&#34;Unresolved error %@, %@&#34;, error, );
            abort();
      }

      //reload Customer list
      NSIndexPath *insertionPath = ;
      ;
      ;
    }
}
</code></pre>

<p>这是我必须为我们的下一个版本(很快)解决的最大(最严重)缺陷。我将不胜感激任何帮助!谢谢!</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>从修复泄漏的 NSFetchedResultsCONtroller 开始</p>

<pre><code>-(void) CustomerSelectedRaised:(NSNotification *)notif
{
    /*...*/
    fetchedResultsController = nil;
    /*...*/
}
</code></pre>

<p>你不应该有多个 NSFetchedResultsControllers 都报告对同一个 tableview 的更改。我认为这就是正在发生的事情。除非 NSFRController 被释放,否则它将向其委托(delegate)报告更改</p></p>
                                   
                                                <p style="font-size: 20px;">关于iphone - NSFetchedResultsController 和插入记录的问题,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/5068511/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/5068511/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: iphone - NSFetchedResultsController 和插入记录的问题