Подтвердить что ты не робот

Как назначить отношения CoreData "многие ко многим" в Swift?

У меня есть класс NSManagedObject

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

Как добавить новое отношение к dogBreed? Если я изменяю тип var на NSMutableSet, изменения не сохраняются в базе данных. Любые идеи?

4b9b3361

Ответ 1

Как и в Xcode 7 и Swift 2.0, в примечании к выпуску 17583057 говорится:

Атрибут NSManaged может использоваться как с методами, так и с свойства, для автоматического доступа к базовым Datas Ключ-кодирование, совместимый со многими аксессуарами.

@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)

Ответ 2

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.

Достаточно создать отношения в одном из управляемых объектов, второй - с обратной ссылкой. (То же, что было с Objective-C)

Важно: Чтобы все это работало, вы должны убедиться, что имена классов объектов в вашей модели CoreData содержат имя вашего модуля. Например. MyProjectName.Disease

Ответ, вдохновленный: Настройка отношения NSManagedObject в Swift

Ответ 3

Если вы ищете простой подход, просто используйте это.

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

Реализация:

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

Вместо того, чтобы писать один и тот же метод для каждого класса NSManageObject, который ему нужен.

Ответ 4

На самом деле вы можете просто написать:

@NSManaged var dogBreed: Set<DogBreed>

И используйте методы insert и remove Set напрямую.

Ответ 5

Как расширение для @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>)
    }
}

Вам нужно вызвать обработчики willChange и didChange, чтобы правильно добавить объект в отношение ко многим во Swift.

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

Ответ 6

@Nycen имеет лучшее решение для Xcode 7 с теперь автоматически реализованными методами, однако обратите внимание, что проблема NSOrderedSet почти невероятно все еще существует (см. этот вопрос), поэтому, если вы используете NSOrderedSet для своих отношений вместо NSSet, вам все равно придется использовать обходной путь.

(Я бы прокомментировал вместо публикации нового ответа, однако мне не хватает точек)

Ответ 7

Если вам нужно использовать NSOrderedSet вместо NSSet, я использовал следующий код, который упрощает доступ к методам NSMutableOrderedSet для добавления, вставки и удаления объектов.

@NSManaged private var myOrderedSet: NSOrderedSet

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