3

如图所示,我有以下模型。

替代文字 http://img521.imageshack.us/img521/9741/schermata20100224a12251.png

我的应用程序需要刷新 B 的每个实例,因此在每个实例中viewWillAppear,我都需要删除模型中的所有 B。删除 B 时,与 C 的关系的级联删除规则将删除所有 C,然后级联到所有 D。A 和 E 是常量。

我对每个对象都有 DeleteRule 如下:

A: b - Cascade
B: c - Cascade, a - Nullify
C: b - Nullify, d - Cascade
D: c - Nullify, e - Nullify
E: d - Cascade

或者

A -(cascade)->> B -(cascade)-> C -(cascade)->> D -(nullify)-> E
A <-(nullify)- B <-(nullify)- C <-(nullify)- D <-(nullify) E

我在级联所有 B、C、D 上的删除时遇到问题。我的 fetchRequest 对象返回 A 中 B 的每个实例,然后我-deleteObject:从 managedObjectContext 调用每个 B 上的 。但是在对 [managedObjectContext save:&error] 的调用中有 EXC_BAD_ACCESS

有人可以告诉我我做错了什么吗?我是否对每个实体的 DeleteRule 有问题,还是问题出在其他地方?处理三个对象 B、C、D 的级联删除的最佳实践是什么?

编辑:

这是引发错误时的堆栈跟踪:

  #0    0x01d843ae in ___forwarding___
  #1    0x01d606c2 in __forwarding_prep_0___
  #2    0x01c618b6 in -[NSFetchedResultsController(PrivateMethods) _managedObjectContextDidChange:]
  #3    0x0003263a in _nsnote_callback
  #4    0x01d4f005 in _CFXNotificationPostNotification
  #5    0x0002fef0 in -[NSNotificationCenter postNotificationName:object:userInfo:]
  #6    0x01bc217d in -[NSManagedObjectContext(_NSInternalNotificationHandling) _postObjectsDidChangeNotificationWithUserInfo:]
  #7    0x01c21763 in -[NSManagedObjectContext(_NSInternalChangeProcessing) _createAndPostChangeNotification:withDeletions:withUpdates:withRefreshes:]
  #8    0x01ba65ea in -[NSManagedObjectContext(_NSInternalChangeProcessing) _processRecentChanges:]
  #9    0x01bdc728 in -[NSManagedObjectContext save:]

这是我尝试将 NSZombieEnabled & MallocStackLogging 设置为 YES 时控制台中的日志:

  2010-02-24 15:41:39.803 Foo[2591:207] deleting object: FUM5
  2010-02-24 15:41:40.515 Foo[2591:207] *** -[viewController controllerWillChangeContent:]: message sent to deallocated instance 0x7e54510

编辑 2:添加源代码

我试图通过创建一个具有图像中确切架构的新项目来重新创建这种情况。你可以从这里下载。还有一个 README 文本。希望我已经提供了足够的信息。

4

2 回答 2

3

我相信问题可能在于 C 和 D 之间的必要关系。如果您将图表配置为:

  1. 每个 C 至少需要一个 D。
  2. 许多 C 的实例指向同一个 D。

然后在某个时候,C 可能会发现它所需的关系已被取消。如果它仍然尝试访问 D,那将触发 EXC_BAD_ACCESS。(如果每个 E 需要一个 D,你可能会遇到同样的问题)

调试我建议,

  • 将关系 C-->D 设置为可选,看看错误是否消失。
  • 从 C-->D 开始,一次将级联更改为空值,然后查看错误是否消失。
  • 如果您有类,请检查实例是否不共享实体图之外的某些共同对象。例如,C 类和 D 类都引用了同一个图像,但该图像不是实体的一部分。如果外部引用没有正确保留,也可能导致类似的崩溃。
  • 在调用后立即将保存移至删除每个 B。在删除之前记录每个 B 和它的 Cs。这样您就可以准确地看到保存失败的情况以及图表的状态。

编辑01:

好的,我查看了您的代码,发现了问题。

问题是您将 A 的“b”关系设置为 required。当您删除 B 时,它会引发此错误:

2010-02-24 16:14:02.064 CoreDataTestDeleteRule[20887:207] Unresolved error Error Domain=NSCocoaErrorDomain Code=1580 UserInfo=0x3d0b450 "Operation could not be completed. (Cocoa error 1580.)"
2010-02-24 16:14:06.340 CoreDataTestDeleteRule[20887:207] Unresolved error Error Domain=NSCocoaErrorDomain Code=1580 UserInfo=0x3d19980 "Operation could not be completed. (Cocoa error 1580.)", {
    NSLocalizedDescription = "Operation could not be completed. (Cocoa error 1580.)";
    NSValidationErrorKey = b;
    NSValidationErrorObject = <A: 0x3b2faf0> (entity: A; id: 0x3d05330 <x-coredata://6870AF7C-E28F-4B4E-80AB-09C648651179/A/p1> ; data: {
    b =     (
    );
    name = a;

顺便说一句,数字核心数据错误代码的文本错误可以在中找到CoreDataErrors.h

这是有道理的,因为您需要 A 拥有 ab,然后您删除所有 b。只需将 A->>B 关系设置为 optional 即可防止错误并允许代码正常运行。

您的代码还有其他一些问题。一些自动生成的类没有正确显示。例如,Bh 的界面如下所示:

#import <CoreData/CoreData.h>

@class A;

@interface B :  NSManagedObject  
{
}

@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) A * a;
@property (nonatomic, retain) NSManagedObject * c;

@end

什么时候应该看起来像:

#import <CoreData/CoreData.h>

@class A;
@class C;

@interface B :  NSManagedObject  
{
}

@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) A * a;
@property (nonatomic, retain) C * c;

@end

我不确定他们为什么没有正确生成。

我还建议不要使用短变量和类名。Objective-c 有一个全局名称空间,使用单字母符号会导致名称冲突。你永远不知道还有谁着急。我建议使用旧的二战风格的拼音字母(现代的也有碰撞的风险)和名称测试类:Adam、Baker、Charlie、David、Eddy 等。

看起来我们都专注于 B<->C<->>D 关系,而忽略了放眼更远的地方。是军方“目标锁定”的程序员调试版。你被困在一个问题的概念上,无法摆脱自己。

于 2010-02-24T13:54:30.897 回答
2

What are you doing in your NSFetchedResultsControllerDelegate methods? Based on the stack trace it looks like you are doing something funny in one of those. Ideally those delegates should only be updating the UITableView that they are attached to. If you are doing something either with the NSManagedObject instances or the NSManagedObjectContext in one of those methods it can cause a crash like this.

I would suggest putting a breakpoint on objc_exception_throw and that can give you more information about the exact point the issue is occurring.

Update

I have looked at the code and you are trying to delete a B while A has a required property for that B. This is causing a validation error. You can't delete an object that another object has as a required relationship.

于 2010-02-24T19:25:07.647 回答