2014-10-17 9 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 
} 

Voglio fare un metodo che mi permette di inizializzare i nuovi oggetti con questo invito:Come creare un inizializzatore designato per la sottoclasse NSManagedObject in Swift?

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

Ma ottengo l'errore:

Convenience initializer for Alternative must delegate with self.init 

cosa ho bisogno di cambiare nella mia initalizer per far funzionare il mio esempio di utilizzo?

risposta

29

Un inizializzatore convenienza necessario chiamare l'inizializzatore designato il self:

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

che sarebbe chiamato come

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

Inoltre, si potrebbe anche spostare la creazione della descrizione dell'entità nella inizializzazione convenienza invece di passare come argomento (come motivato da risposta di Mundi):

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

Domanda aggiuntiva rapida @ martin-r: Sto cercando di collocarli in un'estensione su NSManagedObject. Pensi che questo dovrebbe essere possibile, visto che sto ottenendo un errore di compilazione. Sembra che stia cercando NS_DESIGNATED_INITIALIZER da NSManagedObject.h da utilizzare. qualche idea? – Damien

+0

@Damien: non senza visualizzare il codice effettivo e il messaggio di errore esatto. –

+0

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

9

ho semplicemente fatto questo con una funzione di classe:

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 
} 

che si può chiamare così (quasi abbastanza):

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

Quindi non è possibile creare un inizializzatore designato con 'Alternativa (" terza piattaforma ", True, entityDescription, managedObjectContext)'? La mia opinione è che non sembra buono con Alternative.newInstance (...) – hakonbogen

+2

+1 per * non * che ha bisogno di passare una descrizione di entità nell'inizializzatore. –

+0

Puoi dargli un altro nome a tuo piacimento invece di 'newInstance()'. Inoltre, vuoi ancora i parametri con nome, non solo un elenco di parametri, altrimenti il ​​tuo codice sarà meno leggibile. - In sintesi, la soluzione del metodo di classe non è più lunga o meno estetica di altri inizializzatori. – Mundi

2

Devi chiama un inizializzatore designato dal tuo inizializzatore di convenienza. Inoltre, non si restituisce nulla da alcun inizializzatore.

Per soddisfare le regole, descritte nella documentazione di Apple Swift, è necessario innanzitutto un inizializzatore designato per la propria sottoclasse, che chiama init() della sua superclasse, quindi è possibile offrire un inizializzatore conveniente a cui è consentito solo chiamare un inizializzatore designato dalla sua dichiarazione di classe.

Ciò funzionerebbe: (aggiornato:. Tenere conto che le proprietà dei dati fondamentali contrassegnati con @NSManaged vengono inizializzati automaticamente dal runtime Grazie @ 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

Le proprietà dei dati di base (contrassegnate con '@ NSManaged') vengono inizializzate automaticamente dal runtime. –

+0

Ciò causerà un problema. vedi questa domanda: http://stackoverflow.com/questions/26202346/error-with-swift-and-core-data-fatal-error-use-of-unimplemented-initializer-i – rintaro

2

Swift 3.1 soluzione:

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 
}