質問

画像でわかるように、私は次のモデルを持っています。

代替テキスト 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: それぞれの B で、managedObjectContext から取得します。しかし [managedObjectContext save:&error] の呼び出しに EXC_BAD_ACCESS があります.

誰かが私が間違っていることを教えてくれませんか?各エンティティの DeleteRule に問題があるのでしょうか、それとも別の場所に問題があるのでしょうか?3 つのオブジェクト 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 テキストもあります。十分な情報を提供できたことを願っています。

役に立ちましたか?

解決

あなたのNSFetchedResultsControllerDelegate方法で何をしているのか?あなたがそれらのいずれかに面白いことをやっているように、スタックトレースに基づいて、それが見えます。理想的には、これらの代表者は、彼らだけが接続されていることをUITableViewを更新する必要があります。あなたはどちらかNSManagedObjectインスタンスまたはそれらのいずれかの方法でNSManagedObjectContextで何かをやっている場合、それはこのようにクラッシュを引き起こす可能性があります。

私はobjc_exception_throwにブレークポイントを置くことを示唆している、それはあなたに問題が発生している正確なポイントに関する詳細な情報を与えることができます。

更新

私は、コードを見てきました、あなたはAがBにこれは、検証エラーの原因となっていることのために必要な性質を持っていながら、Bを削除しようとしています。あなたは他のオブジェクトが必要な関係として持っているオブジェクトを削除することはできません。

他のヒント

問題は、C と D の間の必要な関係にあるのではないかと思います。グラフが次のように構成されている場合:

  1. 各 C には少なくとも 1 つの D が必要です。
  2. C の多くのインスタンスは同じ D を指します。

その後、ある時点で C は、必要な関係が無効になったことに気づく可能性があります。いずれにしても D にアクセスしようとすると、EXC_BAD_ACCESS がトリガーされます。(各 E に 1 つの D が必要な場合、同じ問題が発生する可能性があります)

デバッグするには、次のようにすることをお勧めします。

  • C-->D の関係をオプションとして設定し、エラーが解消されるかどうかを確認します。
  • C-->D から始めて一度に 1 つずつカスケードを null に変更し、エラーが解消されるかどうかを確認します。
  • クラスがある場合は、インスタンスがエンティティ グラフの外で共通のオブジェクトを共有していないことを確認してください。たとえば、C クラスと D クラスの両方に同じイメージへの参照がありますが、そのイメージはエンティティの一部ではありません。外部参照が適切に保持されていない場合も、同様のクラッシュが発生する可能性があります。
  • 各 B を削除するには、呼び出しの直後に保存を移動します。削除する前に各 B を記録し、それが C になります。こうすることで、保存が失敗したか、失敗したときにグラフがどのような状態になっているかを正確に確認できます。

編集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 には b が必要であり、その後すべての b を削除するため、これは理にかなっています。A->>B 関係をオプションに設定するだけで、エラーが防止され、コードが正常に実行できるようになります。

コードには他にもいくつかの問題があります。自動生成されたクラスの一部は正しく結果が得られませんでした。たとえば、B.h のインターフェイスは次のようになります。

#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 にはグローバル名前空間があり、単一文字のシンボルを使用すると名前の衝突が発生します。他に誰が急いでいたかわかりません。私は、古い第二次世界大戦スタイルの発音アルファベット (現代のものでも衝突の危険があります) を使用し、テスト クラスに名前を付けることをお勧めします。アダム、ベイカー、チャーリー、デヴィッド、エディなど。

私たちは二人とも B<->C<->>D という関係に集中して、もっと遠くを見ることを怠ったようです。これは、軍の「目標固定」のプログラマーによるデバッグ版です。問題の 1 つの概念に囚われて、そこから抜け出すことができません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top