【问题标题】:Why is NSFetchedResultsController performFetch: crashing when recreating an NSFetchedResultsController with an equivalent NSFetchRequest?为什么 NSFetchedResultsController performFetch: 在使用等效 NSFetchRequest 重新创建 NSFetchedResultsController 时崩溃?
【发布时间】:2009-10-05 21:49:28
【问题描述】:

为什么[NSFetchedResultsController performFetch:] 在使用等效的NSFetchRequest 重新创建NSFetchedResultsController 时会崩溃?

我有一个具有线程表视图控制器(消息线程)的应用程序。当您点击一个线程时,它会加载另一个表视图控制器,该控制器使用 NSFetchedResultsController 来获取该线程的所有消息并显示它们。我使用 NSFetchedResultsController 因为我可以在后台加载消息/删除/添加新消息,而根本不用担心显示它们。

第二个表格视图控制器用于所有线程,所以当我点击返回然后点击另一个线程时,我只是删除当前的 NSFetchedResultsController 并为新线程设置一个新的。

以下是重现 CRASH 的步骤:

  1. 点按一个话题,它就会向我显示消息。
  2. 重新加载消息,以便 NSFetchedResultsController 用于显示新消息。
  3. 返回。
  4. 点击另一个线程。
  5. 返回。
  6. 点击第一个线程。

在点击 NSFetchedResultsController 时,会创建与第一个相同的 NSFetchedResultsController。 (相同的缓存和一切)。如果它给出这个错误和崩溃,而不是像它那样工作:

Program received signal: “EXC_BAD_ACCESS”.

NSFetchedResultsController 正在向已释放的对象发送消息。

这是堆栈跟踪:

#0  0x95ffd688 in objc_msgSend
#1  0x0060699b in -[NSFetchedResultsController(PrivateMethods) _computeSectionInfo:error:]
#2  0x00601bf0 in -[NSFetchedResultsController performFetch:]
#3  0x0001c170 in -[CMNewMessagesViewController loadMessagesViewControllerForThread:showProfile:] at CMNewMessagesViewController.m:331

3 是我的方法

有什么想法吗?任何帮助将不胜感激。


已解决!

这是我的错。我使用的是从另一个键值派生的 sectionNameKeyPath。只要 NSFetchRequest 按该键值排序就可以了。问题是它是动态生成的,因为我不想为此浪费数据库中的空间。我在 NSManagedObject 类中使用了一个实例变量,它由 didTurnIntoFault 清理。

现在,我认为必须创建实例变量然后丢弃,然后在某个时候重新创建,从而使 NSFetchedResultsController 的排序停止。

这解释了为什么没有 sectionNameKeyPath 或委托来解决问题。

现在,我已经切换到 CoreData 对象中保存的键值,它似乎工作得很好。

【问题讨论】:

    标签: iphone core-data crash


    【解决方案1】:

    当调用 performFetch 时,我在系统堆栈的深处得到了相同的 EXC_BAD_ACCESS 信号。更改缓存或其他任何东西都没有帮助。

    - (void)viewDidLoad {
        [super viewDidLoad];
    
        MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
        managedContext = [appDelegate managedObjectContext];
    
        NSError *error = nil;
        NSFetchedResultsController *frC = self.fetchedResultsController;
        if (![frC performFetch:&error]) {
            /* */
        }
    }
    

    最近我发现了一个要添加的小 sn-p。实际上,问题在于我使用 iOS 内存管理的方式(或者没有使用过)。

    - (NSFetchedResultsController *)fetchedResultsController {
        if (fetchedResultsController != nil) {
            return fetchedResultsController;
        }
    
        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
        NSEntityDescription *entity = [NSEntityDescription entityForName:@"Asiakasrekisteri" inManagedObjectContext:managedContext]; [fetchRequest setEntity:entity];
    
        [fetchRequest setFetchBatchSize:200];
    
        NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"yritys" ascending:YES]; NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
    
        [fetchRequest setSortDescriptors:sortDescriptors];
    
        NSFetchedResultsController *aFetchedResultsController =
            [[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedContext sectionNameKeyPath:nil cacheName:nil] retain];
    
        aFetchedResultsController.delegate = self;
        self.fetchedResultsController = aFetchedResultsController;
    
        [aFetchedResultsController release];
        [fetchRequest release];
        [sortDescriptor release];
        [sortDescriptors release];  
        return fetchedResultsController;
    } 
    

    aFetchedResultsController 的独立生命周期确实很短,但它在 performFetch 之前就被释放了。 retain 确实有帮助,结果控制器保持分配。

    【讨论】:

      【解决方案2】:

      这是我的错。我使用的是从另一个键值派生的 sectionNameKeyPath。只要 NSFetchRequest 按该键值排序就可以了。问题是它是动态生成的,因为我不想为此浪费数据库中的空间。我在 NSManagedObject 类中使用了一个实例变量,它由 didTurnIntoFault 清理。

      现在,我认为必须创建实例变量然后丢弃,然后在某个时候重新创建,从而使 NSFetchedResultsController 的排序停止。

      这解释了为什么没有 sectionNameKeyPath 或委托来解决问题。

      现在,我已切换到 CoreData 对象中保存的键值,它似乎工作得很好。

      【讨论】:

        猜你喜欢
        • 2011-02-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多