2015-11-10 4 views
1

У меня есть класс, который наследуется от NSManagedObject. Я использую этот объект для данных модели, и он также сохраняется.Downcasting NSManagedObject в Swift Core Data

class Foo: NSManagedObject { 

    @NSManaged var firstVar: String 
    @NSManaged var secondVar: String 

    let entity = NSEntityDescription.entityForName("Foo", inManagedObjectContext: managedObjectContext) 
    let createdManagedObject = NSManagedObject(entity: entity!, insertIntoManagedObjectContext: managedObjectContext) as? Foo 

} 

Я могу создать объект и получить экземпляр NSManagedObject, но я не могу его обратное приведение фактического класса. На самом деле, если я опускаю его, то формирую необязательное значение, тогда я получу нулевое значение, и если я опустошу с распаковкой, тогда он сработает. Когда downcast с инспектором отладчика nil value показывает тип: Module.Foo, который, я считаю, является корнем проблемы.

Конечно, я попытался с именами класса в .xcmodel инспекторов, пытался назвать Entity в Module.Foo, но последний не допускаются, как из Xcode 7 больше в любом случае.

Все вместе: без успеха. Теперь мне нужно получить доступ к объекту Foo через KV, что довольно неудобно.

Кто-нибудь еще решила эту проблему?

EDIT: Добавление кода для демонстрации создания и подбрасывания. У меня были проблемы с Xcode 7.0, а теперь с 7.1.1

+3

Не могли бы вы показать, как вы его получите, и как вы его преуменьшаете? –

+2

Пробовал ли вы различные решения в http://stackoverflow.com/questions/25076276/unable-to-find-specific-subclass-of-nsmanagedobject и http://stackoverflow.com/questions/26613971/coredata-warning- неспособные к нагрузке-класс по имени? Это происходит в вашей основной программе или модульном тесте или в рамках? –

+0

Я на самом деле работаю над проектом с основными данными, и у меня нет проблем: 'self.entry = NSEntityDescription.insertNewObjectForEntityForName (имя_общества, inManagedObjectContext: managedObjectContext) как? Foo'. Можете ли вы опубликовать более подробную информацию? –

ответ

0

Вам необходимо отредактировать конфигурацию модели данных, чтобы сообщить CoreData, какой класс использовать для определенного объекта. Фактическое имя объекта не влияет на экземпляр класса.

enter image description here

+0

Да, это было сделано, конечно. Проблема в том, что возвращаемый класс не Foo, а Module.Foo, поэтому downcast не увенчался успехом. – mbpro

+0

Вы должны использовать «.Foo» (точка в начале) и явно не указывать модуль .. он будет определен во время сборки. Затем 'NSEntityDescription.insertNewObjectForEntityForName (entityName: String, inManagedObjectContext context: NSManagedObjectContext)' должен работать –

+0

К сожалению, это не сработало ни с 7.1 – mbpro

0

Вы должны добавить objc аннотацию к классу:

@objc(Foo) 
class Foo: NSManagedObject { 
    ... 
} 
+0

Пробовал. Не помогает. Тем не менее, я считаю, что если вы наследуете NSObject или подкласс, директива @objc не нужна, это должно быть выведено. – mbpro

+0

В моем случае это было необходимо, и я расширил NSManagedObject. –

+0

Если вы установите модуль объекта в «Текущий модуль продукта», вы должны * не * добавить '@objc (...)', по крайней мере, это то, что я испытал. –

0

Вам нужно создать экземпляр Foo-класса напрямую:

let createdManagedObject = Foo(entity: entity!, insertIntoManagedObjectContext: managedObjectContext) 

Если вы все еще хотите encapsule код для управления CoreData, вы можете сделать что-то похожее на следующее:

static func newInstanceForEntityName(name: String, context: NSManagedObjectContext) -> NSManagedObject { 

    let anyType: AnyObject.Type = NSClassFromString(name)! 
    let nsmType: NSManagedObject.Type = anyType as! NSManagedObject.Type 

    let entity = NSEntityDescription.entityForName(name, inManagedObjectContext: context) 

    return nsmType.init(entity: entity!, insertIntoManagedObjectContext: context) 
} 

Вы можете использовать его как:

let foo = newInstanceForEntityName("Foo", context: context) as! Foo 
+0

Это на самом деле способ, как я сделал это в другом классе, но спасибо, что показал это! :) – mbpro

1

кажется, что главная проблема была цель. Спасибо Martin R за то, что указал мне на проблему. Проблема заключалась в том, что и код в главном приложении был частью или другой целью, аналогичной тестам. Когда объект был извлечен из основных данных, это класс подпись была Target.Foo и если вы пытались бросить его Foo в Target2, вы получили сообщение об ошибке, отлитой из Target.Foo в Target2.Foo не представляется возможным, и, к сожалению, это сообщение Бесполезным 'Показывать в журнале, если журнал не был пуст?

Это не имеет значения, как вы назвали класс или модуль, если при установлении ниже:

enter image description here

Единственное, что имеет значение в том, что ваш .xcmodel находится в одной и той же цели чем код, который обращается к нему.

Смежные вопросы