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

Как определить отношения CoreData в Swift?

В CoreData я определил неупорядоченное отношение to-many от Node до Tag. Я создал объект Swift следующим образом:

import CoreData
class Node : NSManagedObject {
    @NSManaged var tags : Array<Tag>
}

Теперь я хочу добавить Tag в экземпляр Node, например:

var node = NSEntityDescription.insertNewObjectForEntityForName("Node", inManagedObjectContext: managedObjectContext) as Node
node.tags.append(tag)

Однако это не выполняется со следующей ошибкой:

Завершение приложения из-за неперехваченного исключения "NSInvalidArgumentException", причина: "Недопустимый тип отношения для многих: property =" tags "; желаемый тип = NSSet; данный тип = _TtCSs22ContiguousArrayStorage000000000B3440D4; value = (     msgstr" ).

Каков правильный тип отношений to-many?

4b9b3361

Ответ 1

Чтобы иметь возможность работать с отношениями "один ко многим" в Swift, вам нужно определить свойство как:

class Node: NSManagedObject {
    @NSManaged var tags: NSSet
}

Если вы попытаетесь использовать NSMutableSet, изменения не будут сохранены в CoreData. И, конечно, рекомендуется определить обратную ссылку в Node:

class Tag: NSManagedObject {
    @NSManaged var node: Node
}

Но все же Swift не может генерировать динамические аксессоры во время выполнения, поэтому нам нужно определить их вручную. Очень удобно определять их в классе extension и помещать в файл Entity+CoreData.swift. Bellow - это содержимое файла Node+CoreData.swift:

extension Node {
    func addTagObject(value:Tag) {
        var items = self.mutableSetValueForKey("tags");
        items.addObject(value)
    }

    func removeTagObject(value:Tag) {
        var items = self.mutableSetValueForKey("tags");
        items.removeObject(value)
    }
}

Использование:

// somewhere before created/fetched node and tag entities
node.addTagObject(tag)

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

Ответ 2

Как и в 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 addTagsObject(tag: Tag)
@NSManaged func removeTagsObject(tag: Tag)
@NSManaged func addTags(tags: NSSet)
@NSManaged func removeTags(tags: NSSet)

Ответ 3

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

@NSManaged var employees: Set<Employee>

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

Ответ 4

Основываясь на ответе @Keenle, если вы хотите быть нахальным и лаконичным и быть в состоянии сказать

node.tags.append(tag)

можно обернуть вызов self.mutableSetValueForKey:

class Node: NSManagedObject {

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