2014-10-17 3 views
27
class Alternative: NSManagedObject { 

    @NSManaged var text: String 
    @NSManaged var isCorrect: Bool 
    @NSManaged var image: NSData 
} 

convenience init(text: String, isCorrect: Bool, entity: NSEntityDescription, insertIntoManagedObjectContext context: NSManagedObjectContext!) { 
     let alternative = Alternative(entity: entity, insertIntoManagedObjectContext: context) as Alternative 
     alternative.text = text 
     alternative.isCorrect = isCorrect 
     return alternative 
} 

Я хочу сделать метод, который позволяет мне инициализировать новые объекты с этим вызовом:Как создать назначенный инициализатор для подкласса NSManagedObject в Swift?

let newAlternative = Alternative("third platform", True, entityDescription, managedObjectContext) 

Но я получаю сообщение об ошибке:

Convenience initializer for Alternative must delegate with self.init 

Что мне нужно изменить в моей initalizer чтобы мой пример использования работал?

ответ

29

Удобный инициализатор должен назвать назначенный инициализатору на self:

convenience init(text: String, isCorrect: Bool, entity: NSEntityDescription, insertIntoManagedObjectContext context: NSManagedObjectContext!) { 
    self.init(entity: entity, insertIntoManagedObjectContext: context) 
    self.text = text 
    self.isCorrect = isCorrect 
} 

, который будет называться

let newAlternative = Alternative(text: "third platform", isCorrect: true, 
    entity: entityDescription, insertIntoManagedObjectContext: managedObjectContext) 

Кроме того, вы также можете переместить создание описания объекта в удобство инициализаторе вместо того, чтобы передать его в качестве аргумента (как мотивировано ответ Мунди):

convenience init(text: String, isCorrect: Bool, insertIntoManagedObjectContext context: NSManagedObjectContext!) { 
    let entity = NSEntityDescription.entityForName("Alternative", inManagedObjectContext: context)! 
    self.init(entity: entity, insertIntoManagedObjectContext: context) 
    self.text = text 
    self.isCorrect = isCorrect 
} 
+0

Быстрый дополнительный вопрос @ martin-r: Я пытаюсь поместить их в расширение на NSManagedObject. Как вы думаете, это должно быть возможно, так как я получаю ошибку компиляции. Кажется, он ищет NS_DESIGNATED_INITIALIZER из NSManagedObject.h, который будет использоваться. Есть предположения? – Damien

+0

@Damien: Не видно фактического кода и точного сообщения об ошибке. –

+0

https: //gist.github.com/dglancy/2f1e313cfcc7d61cff8c – Damien

9

Я просто сделал это с классом функции:

class func newInstance(text: String, notes:String, 
        context: NSManagedObjectContext) -> Item { 
    var item = NSEntityDescription.insertNewObjectForEntityForName("Item", 
       inManagedObjectContext: context) as Item 
    item.notes = notes 
    item.text = text 
    return item 
} 

который можно назвать, как это (почти как миленькие):

let item = Item.newInstance(text, notes:notes) 
+0

Таким образом, невозможно создать назначенный инициализатор с помощью «Альтернатива» («третья платформа», «Истина», «СущностьDescription, managedObjectContext»)? Мое мнение таково, что он не выглядит так хорошо с Alternative.newInstance (...) – hakonbogen

+2

+1 для * не * необходимости передать описание сущности в инициализатор. –

+0

Вы можете присвоить ему другое имя вместо 'newInstance()'. Кроме того, вам все еще нужны именованные параметры, а не только список параметров, иначе ваш код будет менее читаемым. - Таким образом, решение метода класса на самом деле не является более длинным или менее эстетичным, чем другие инициализаторы. – Mundi

2

Вы должны вызовите назначенный инициализатор из вашего инициализатора удобства. Кроме того, вы ничего не возвращаете из любого инициализатора.

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

Это будет работать: (Обновлено:. Принимая во внимание, что основные свойства данных, отмеченные @NSManaged инициализируются автоматически во время выполнения Благодаря @Martin R)

init(text: String, isCorrect: Bool, image: NSData, entity: NSEntityDescription, insertIntoManagedObjectContext context: NSManagedObjectContext!) { 
    super.init(entity: entity, insertIntoManagedObjectContext: context) 
} 

convenience init(text: String, isCorrect: Bool, entity: NSEntityDescription, insertIntoManagedObjectContext context: NSManagedObjectContext!) { 
    self.init(text: text, isCorrect: isCorrect, entity: entity, insertIntoManagedObjectContext: context) 
} 
+1

Основные свойства данных (помечены символом '@ NSManaged') инициализируются автоматически по времени выполнения. –

+0

Это вызовет проблему. см. этот вопрос: http://stackoverflow.com/questions/26202346/error-with-swift-and-core-data-fatal-error-use-of-unimplemented-initializer-i – rintaro

2

Swift 3,1 решение:

convenience init(text: String, isCorrect: Bool, image: NSData, moc: NSManagedObjectContext) { 
     let entity = NSEntityDescription.entity(forEntityName: "Alternative", in: moc) 
     self.init(entity: entity!, insertInto: moc) 
     // vars 
     self.text = text 
     self.isCorrect = isCorrect 
     self.image = image 
}