2

Core Data を使用して、次の対多関係でタグ付けシステムをセットアップしようとしています。

article.tags <<------->> tag.articles

このシナリオでは、articleは多数の を持つことができtags、同じものtagsを複数の に割り当てることができますarticles。のタグが編集されるたびに、以前に関連付けられていたものarticleをすべて削除し、関連性のあるものを再度追加します。次のようにします。tagsarticle

// Remove any existing tags from this article
if(article.tags.count)
{
    NSSet *existingEventTags = [article.tags copy];
    for (NSManagedObject *tag in existingEventTags)
    {
        [[article mutableSetValueForKey:@"tags"] removeObject:tag];
        [moc deleteObject:tag];
    }
}

// Now re-assign any applicable tags to this article
for(NSString *tag in tags)
{
    Tag *existingTag = [self existingTagWithString:tag];
    if(existingTag)
    {
        [article addTagsObject:existingTag];
    }
    else
    {
        NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Tag" inManagedObjectContext:moc];
        Tag *newTag = (Tag *)[[NSManagedObject alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:moc];
        newTag.name = tag;
        [article addTagsObject:newTag];
    }
}

私の質問は、2 つの関係に関連付けられた削除規則をどのように処理するのが最善かということです。基本的に私が探している動作は、tagからを削除するときに、他にタグ付けされていarticleない場合にのみ完全に削除したいということです。articles

これを達成するために、tag.articles関係を Nullify に設定し、articles.tags関係を Cascade に設定しました。ただし、記事を削除すると、それに関連付けられているタグは (他の記事に関連付けられているかどうかに関係なく) 削除されます。これをテストするために、以下に含める簡単なデバッグ関数を作成しました。

- (void)debugTags
{
    NSFetchRequest *request = [[NSFetchRequest alloc] init];

    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Tag" inManagedObjectContext:moc];
    [request setEntity:entity];

    // Execute the fetch.
    NSError *error = nil;
    NSArray *objects = [moc executeFetchRequest:request error:&error];
    if (objects != nil && [objects count] > 0)
    {
        NSLog(@"Found %d tags", [objects count]);
        for(Tag *tag in objects)
        {
            NSLog(@"\t%@ (%d events)", tag.name, tag.articles.count);
        }
    }
    else
    {
        NSLog(@"No tags found!");
    }
}

完全を期すために、ここに出力例を示します ( articles2 つの共有tags: food と fastfood を使用した 2 つの作成を示します)。1 つを削除した後もarticle、店内にはまだ食べ物やファストフードがあると思いますが、関係数は 1 です。

Before deletion
---------------

Found 4 tags
   breakfast (1 events)
   food (2 events)
   fastfood (2 events)
   lunch (1 events)

After deletion
--------------

Found 1 tags
   lunch (1 events)
4

2 に答える 2

5

この問題に対して私が見つけた最善の解決策は、両方の削除ルールを Nullify に設定し、私articleNSManagedObject prepareForDeletionメソッドで削除を処理することでした:

- (void)prepareForDeletion
{
    [super prepareForDeletion];

    for (Tag *tag in self.tags)
    {
        if(tag.events.count == 1)
        {
            [self.managedObjectContext deleteObject:tag];
        }
    }
}
于 2013-02-19T19:03:47.247 に答える
0

削除ルール以外はすべて正しいです。この構成では、CoreData はエラーでコンテキストを保存しません:

 NSValidationErrorKey=events, NSLocalizedDescription=The operation couldn’t be completed. (Cocoa error 1600.), NSValidationErrorValue=Relationship 'articles' on managed object

これを実現するには、tag.articles 関係を Nullify に設定し、articles.tags 関係を Cascade に設定する必要があります。これは期待どおりに機能します。

そして2番目。コードが例外でクラッシュしました: Collection <_NSFaultingMutableSet: 0x841de10> was mutated while being enumerated. リレーションシップのコピーを作成して、安全に列挙します。

    NSSet* tags = [[object valueForKey:@"tags"] copy];
    for (NSManagedObject *tag in tags) {
        [[object mutableSetValueForKey:@"tags"] removeObject:tag];
        [context deleteObject:tag];
    }
于 2013-02-19T08:00:39.893 に答える