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

Настройка отношения NSManagedObject в Swift

Как добавить объект к свойству отношений в подкласс NSManagedObject в Swift?

В Objective-C, когда вы создаете подкласс NSManagedObject в Xcode из модели данных, есть автоматически созданное расширение класса, которое содержит объявления типа:

@interface MyManagedObject (CoreDataGeneratedAccessors)

     - (void)addMySubObject: (MyRelationshipObject *)value;
     - (void)addMySubObjects: (NSSet *)values;

@end

Однако Xcode в настоящее время не обладает этой способностью генерации класса для классов Swift.

Если я попытаюсь вызвать эквивалентные методы непосредственно на объект Swift:

myObject.addSubObject(subObject)

... Я получаю ошибку компилятора в вызове метода, потому что эти сгенерированные аксессоры не видны.

Я объявил свойство отношения как @NSManaged, как описано в документации.

Или мне нужно вернуться к объектам Objective-C для моделей данных с отношениями?

4b9b3361

Ответ 1

Да, что больше не будет работать, Swift не сможет генерировать аксессоров во время выполнения таким образом, он сломает систему типов.

Что вам нужно сделать, это использовать пути ключей:

var manyRelation = myObject.valueForKeyPath("subObjects") as NSMutableSet
manyRelation.addObject(subObject)
/* (Not tested) */

Ответ 2

Как и Xcode 7 и Swift 2.0 (см. примечание к выпуску # 17583057), вы можете просто добавить следующие определения в сгенерированный файл расширений:

extension PersonModel {
    // This is what got generated by core data
    @NSManaged var name: String?
    @NSManaged var hairColor: NSNumber?
    @NSManaged var parents: NSSet?

    // This is what I manually added
    @NSManaged func addParentsObject(value:ParentModel)
    @NSManaged func removeParentsObject(value:ParentModel)
    @NSManaged func addParents(value:Set<ParentModel>)
    @NSManaged func removeParents(value:Set<ParentModel>)
}

Это работает, потому что

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

Добавление этого определения позволит вам добавлять элементы в свои коллекции. Не уверен, почему они не просто сгенерированы автоматически...

Ответ 3

Основные данные в Objective C автоматически создают методы настройки (1):

По умолчанию Core Data динамически создает эффективные общедоступные и примитивные методы get и set accessor для моделируемых свойств (атрибутов и отношений) классов управляемых объектов. Это включает в себя методы кодирования ключа с переменным ключом, такие как addObject: и удаляет:, как описано в документации для объектов mutableSetValueForKey: -managed - эффективно изменяемые прокси-серверы для всех их отношений со многими.

В настоящее время с Swift в Xcode6-Beta2, вам придется реализовать эти аксессуры самостоятельно. Например, если у вас есть отношение неупорядоченных ко многим, от Way до Node, вы должны реализовать addNodesObject следующим образом:

class Way : NSManagedObject {
    @NSManaged var nodes : NSSet

    func addNodesObject(value: Node) {
        self.mutableSetValueForKey("nodes").addObject(value)
    }
}

Здесь вы должны использовать mutableSetValueForKey/mutableOrderedSetValueForKey/mutableArrayValueForKey. На этих наборах/массивах вы можете вызвать addObject, и они будут сохранены на следующем флеше.

Ответ 4

Расширение над решением выше одного-многих отношений - это NSMutableSet, поэтому это позволяет вам напрямую добавлять или удалять Person NSManagedObject для Ролей, в этом случае у Человека есть одна Роль, а Роли имеют много Лица (ов)

Я тестировал это решение под Xcode Beta-3, и это работает!

Этот код выводит Департамент, чтобы упростить отображение кода один на один и один на один, необходимый для доступа к ролям от лица и лиц из роли.

import CoreData


@objc(Person) class Person: NSManagedObject {

    @NSManaged var name: String

    //One to One relationship in your Model
    @NSManaged var roles: Roles

}


@objc(Roles) class Roles: NSManagedObject {

    @NSManaged var role: String

    //One to Many relationship in your Model
    @NSManaged var persons: NSMutableSet

}

extension Roles {

    func addPersonsObject(value: Person) {
        self.persons.addObject(value)
    }

    func removePersonsObject(value: Person) {
        self.persons.removeObject(value)
    }

    func addPersons(values: [Person]) {
        self.persons.addObjectsFromArray(values)
    }

    func removePersons(values: [Person]) {
        for person in values as [Person] {
            self.removePersonsObject(person)
        }
    }

}

Ответ 5

Вместо этого вы можете использовать типизированный Set, что намного проще. Следуя примеру @Nycen и @lehn0058 в предыдущем ответе, вы можете просто написать:

extension PersonModel {
    @NSManaged var parents: Set<ParentModel>?
}

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

Ответ 6

Начиная с Xcode 8 и Swift 3.0, Xcode теперь генерирует аксессоры для отношений. Например, у меня есть класс Store NSManagedObject, который имеет отношение "один-много" к элементам; Я назвал это отношение SellsItems. Сгенерированный класс для Store теперь имеет следующее расширение для добавления и удаления из SellsItems. Добавление или удаление элементов в отношении так же просто, как вызов этих функций.

// MARK: Generated accessors for sellsItems
extension Store {
    @objc(addSellsItemsObject:)
    @NSManaged public func addToSellsItems(_ value: Item)

    @objc(removeSellsItemsObject:)
    @NSManaged public func removeFromSellsItems(_ value: Item)

    @objc(addSellsItems:)
    @NSManaged public func addToSellsItems(_ values: NSSet)

    @objc(removeSellsItems:)
    @NSManaged public func removeFromSellsItems(_ values: NSSet)
}

Ответ 7

Поскольку вам нужно только установить одну сторону отношения для обоих, которые будут установлены в настоящее время, это особенно просто, если у вас есть отношение 1 ↔ many, например. объект отдела имеет несколько объектов Person, тогда вы можете просто использовать:

aPerson.department = aDepartment

Если вы проверите, вы обнаружите, что aDepartment.people(при условии, что это взаимные отношения, которые вы настроили) теперь будет содержать объект "aPerson" Person.

Если отношение много и меньше многих, то одно из более сложных решений, указанных выше, представляется необходимым.

Ответ 8

Скажем, у вас есть следующие объекты:

  • Person
  • Роль
  • Отдел

В вашей организации Person у них есть отношение to-many с Role и to-one с Department. Ваш управляемый объект может выглядеть примерно так:

class Person : NSManagedObject
{
    @NSManaged var roles : Array<Role>
    @NSManaged var department : Department
}

Взаимоотношения с инверсиями (все должны иметь их) требуют, чтобы для установления связи была установлена ​​одна сторона.

Например, если вы устанавливаете свойство Person Department объекту Department, свойство обратного Department.people теперь также имеет этот объект Person, содержащийся внутри.