web-dev-qa-db-ja.com

SwiftでCoreDataに多対多の関係を割り当てる方法は?

NSManagedObjectクラスがあります

class Disease: NSManagedObject {
    @NSManaged var diseaseId: String
    @NSManaged var diseaseName: String
    @NSManaged var dogBreed: NSSet
}

DogBreedに新しい関係を追加するにはどうすればよいですか? var typeをNSMutableSetに変更すると、変更はデータベースに保存されません。何か案は?

24
tadasz

Xcode7およびSwift 2.0の時点で、 リリースノート 17583057は次のように述べています。

NSManaged属性をメソッドとプロパティと共に使用して、コアデータの自動生成されたKey-Value-Coding準拠の多対多のアクセサーにアクセスできます。

@NSManaged var employees: NSSet

@NSManaged func addEmployeesObject(employee: Employee)
@NSManaged func removeEmployeesObject(employee: Employee)
@NSManaged func addEmployees(employees: NSSet)
@NSManaged func removeEmployees(employees: NSSet)

これらは、NSManagedObjectサブクラスで宣言できます。 (17583057)

したがって、次のメソッドを宣言するだけで、残りはCoreDataが処理します。

@NSManaged func addDogBreedsObject(dogBreed: DogBreed)
@NSManaged func removeDogBreedsObject(dogBreed: DogBreed)
@NSManaged func addDogBreeds(dogBreeds: NSSet)
@NSManaged func removeDogBreeds(dogBreeds: NSSet)
21
Nycen

厳密な型システムのため、Swiftは動的ランタイムアクセサーを生成できません。 Diseaseクラスの拡張を作成し、欠落したメソッドを手動で追加できます。これがコードです。

extension Disease {
    func addDogBreedObject(value:DogBreed) {
        var items = self.mutableSetValueForKey("dogBreed");
        items.addObject(value)
    }

    func removeDogBreedObject(value:DogBreed) {
        var items = self.mutableSetValueForKey("dogBreed");
        items.removeObject(value)
    }
}

備考:

拡張子Disease+CoreData.Swiftの個別のファイルを作成することをお勧めします。これは、CoreDataモデルを再生成するときにコードがオーバーライドされないようにするのに役立ちます。

管理対象オブジェクトの1つに関係を作成するだけで十分です。2番目のオブジェクトは、後方参照で更新されます。 (Objective-Cの場合と同じ)

重要:すべてを機能させるには、CoreDataモデルのエンティティのクラス名にモジュール名が含まれていることを確認する必要があります。例えば。 MyProjectName.Disease

回答: SwiftでのNSManagedObject関係の設定

18
Keenle

簡単なアプローチを探しているなら、これを使ってください。

import CoreData
extension NSManagedObject {
    func addObject(value: NSManagedObject, forKey: String) {
        var items = self.mutableSetValueForKey(forKey);
        items.addObject(value)
    }
}

実装:

department.addObject(section, forKey: "employees")

それを必要とするすべてのNSManageObjectクラスに同じメソッドを書く代わりに。

10
naz

実際には、次のように書くことができます。

@NSManaged var dogBreed: Set<DogBreed>

そして、insertremoveメソッドとSetメソッドを直接使用します。

4
FranMowinckel

@Nazの拡張として。そして@Ashのコメントと組み合わせて。 xCode 6.3.1の唯一の実用的なソリューションを見つけました

import CoreData

extension NSManagedObject {
    func addObject(value: NSManagedObject, forKey: String) {
        self.willChangeValueForKey(forKey, withSetMutation: NSKeyValueSetMutationKind.UnionSetMutation, usingObjects: NSSet(object: value) as Set<NSObject>)
        var items = self.mutableSetValueForKey(forKey);
        items.addObject(value)
        self.didChangeValueForKey(forKey, withSetMutation: NSKeyValueSetMutationKind.UnionSetMutation, usingObjects: NSSet(object: value) as Set<NSObject>)
    }
}

Swiftの多対多の関係にオブジェクトを正しく追加するには、willChangeハンドラーとdidChangeハンドラーを呼び出す必要があります。

myManagedObject.addObject(value, forKey: "yourKey")
3
Simon

@Nycenは、自動的に実装されたメソッドを使用したXcode 7の最適なソリューションを提供しますが、NSOrderedSetの問題はほとんど信じられないほど存在することに注意してください( この質問 を参照)。したがって、関係にNSOrderedSetを使用する場合はNSSetでも、回避策を使用する必要があります。

(私は新しい答えを投稿する代わりにコメントしたでしょうが、私はポイントが不足しています)

2
DJB

NSOrderedSetの代わりにNSSetを使用する必要がある場合は、次のコードを使用して、追加、挿入、およびNSMutableOrderedSetメソッドを簡単に取得できるようにしています。オブジェクトを削除します。

@NSManaged private var myOrderedSet: NSOrderedSet

var myMutableOrderedSet: NSMutableOrderedSet {
    return self.mutableOrderedSetValueForKey("myOrderedSet")
}
1
blwinters