2012-04-20 23 views
2

私は、コンテナとアイテムのエンティティを持つコアデータモデルを持っています。コンテナには0個以上のアイテムがあることができます。項目は、少なくとも1つの容器に属している必要があります(それは、複数にすることができます。)コアデータ削除多対多リレーションシップのルール

関係は次のようになります。コンテナが削除された場合に

Container: 
    Relationship: items, Destination: Item, Inverse: itemContainers 
    Optional, To-Many Relationship 
    Delete Rule: Nullify 

Item: 
    Relationship: itemContainers, Destination: Container, Inverse: items 
    Not-Optional, To-Many Relationship 
    Delete Rule: Cascade 

問題が発生します。そのコンテナ内のItemオブジェクトは更新されますが、項目が1つのコンテナのみに存在する場合、itemContainersプロパティはオブジェクトなしのセットです。空のセットがitemContainersのItemのnot-optional設定に違反するため、オブジェクトグラフを保存できません。

もちろん、itemContainers。@ count == 0のようなNSPredicateを使用して空のitemContainersを持つItemオブジェクトを見つけるのは簡単ですが、自動的にこれを行うようにモデルを設定する方法があるはずです。

もっと簡単な方法がありますか?

答えて

0

私は、あなたがあなたのモデルでは、この動作を指定することができると思いブーティの代わりに、それがフェッチすることはありません、あなたはあなたのコンテナの

- (void)removeItemObject:(Item *)value 
{... 
if(![[value itemContainers]count]) 
    [context deleteObject:value]; 
... 
} 
1

私はそれがコアデータが提供する設定オプションのようにきれいではないと知っているが、それが削除されたとき、私は、彼らが0 itemContainers(内部の持っているかどうかをチェックする、それの子を通してContainerオブジェクトサイクルいくつかのプロジェクトItemエンティティを展開してきました「Container.m」):私のアプリで

- (void)prepareForDeletion 
{ 
    NSSet *childItems = [self items]; 

    for (Item *item in childItems) { 
     if ([[item itemContainers] count] > 1) { 
      continue; 
     } 

     [managedObjectContext deleteObject:item]; 
    } 
} 
0

は、私は、アイテムのコンテナ関係をオプションにし、「スマートコンテナ」を介してこれらの無容器の項目へのアクセス権を与えます。

もしあなたがそれを望まないのであれば、あなたは保存失敗を処理し、違反しているオブジェクトを削除しなければならないと思う。

私は、批判的なものにコアデータへのアプローチを変更しています。検証が失敗し、それを処理する用意ができていると仮定します。 iCloud同期を統合するときにさらに重要になります。

4

itemContainersの数を検証することができ、私は同様の問題のために上Tony Arnold's answerを試してみました一度にいくつかの「コンテナ」を削除すると問題が見つかりました(これはOS X 10.8.2上にあります)。管理対象オブジェクトのコンテキストが保存されるまで、コンテナは[item itemContainers]から削除されないため、countは1を超えて残り、itemは決して削除されません。

-[NSManagedObject isDeleted]とカテゴリメソッドNSManagedObjectを使用して次の解決策を考え出しました。

ファイルNSManagedObject+RJSNondeletedObjects.h

#import <CoreData/CoreData.h> 

@interface NSManagedObject (RJSNondeletedObjects) 

- (NSSet *)RJS_nondeletedObjectsForToManyKeyPath:(NSString *)keyPath; 
- (BOOL)RJS_hasOtherNondeletedObjectsForToManyKeyPath:(NSString *)keyPath; 

@end 

ファイルNSManagedObject+RJSNondeletedObjects.m

#import "NSManagedObject+RJSNondeletedObjects.h" 

@implementation NSManagedObject (RJSNondeletedObjects) 

- (NSSet *)RJS_nondeletedObjectsForToManyKeyPath:(NSString *)keyPath 
{ 
    NSSet * result = nil; 

    id allObjectsForKeyPath = [self valueForKeyPath:keyPath]; 

    if (![allObjectsForKeyPath isKindOfClass:[NSSet class]]) return result; 

    result = [(NSSet *)allObjectsForKeyPath objectsPassingTest:^BOOL(id obj, BOOL *stop) 
    { 
     BOOL testResult = ![obj isDeleted]; 
     return testResult; 
    }]; 

    return result; 
} 

- (BOOL)RJS_hasOtherNondeletedObjectsForToManyKeyPath:(NSString *)keyPath 
{ 
    BOOL result = NO; 

    // self will be in the set of nondeleted objects, assuming it's not deleted. So we need to adjust the test threshold accordingly. 
    NSUInteger threshold = [self isDeleted] ? 0 : 1; 
    NSSet * nondeletedObjects = [self RJS_nondeletedObjectsForToManyKeyPath:keyPath]; 
    result = ([nondeletedObjects count] > threshold); 

    return result; 
} 

@end 

Containerクラス

... 
#import "NSManagedObject+RJSNondeletedObjects.h" 
... 
- (void)prepareForDeletion 
{ 
    NSSet *childItems = [self items]; 

    for (Item *item in childItems) { 
     if ([item RJS_hasOtherNondeletedObjectsForToManyKeyPath:@"containers"]) { 
      continue; 
     } 

     [managedObjectContext deleteObject:item]; 
    } 
} 
0

私はこのようにして好きです:

- (void)didChangeValueForKey:(NSString *)inKey withSetMutation:(NSKeyValueSetMutationKind)inMutationKind usingObjects:(NSSet *)inObjects 
{ 
    [super didChangeValueForKey:inKey withSetMutation:inMutationKind usingObjects:inObjects]; 

    if ([inKey isEqualToString:@"YOURRELATIONSHIP"] && self.YOURRELATIONSHIP.count == 0) { 
     [self.managedObjectContext deleteObject:self]; 
    } 
} 
関連する問題