2014-06-11 3 views
33

Sto utilizzando il codice di codice di Swift per Core Data in un nuovo progetto. Il file .xcdatamodeld ha una singola entità definita (Task) con un singolo attributo (name).Come mai posso trasmettere a NSManagedObject ma non al tipo della mia entità?

Ho un file Task.swift che assomiglia a questo:

import CoreData 

class Task: NSManagedObject { 
    @NSManaged var name: String 
} 

Quando ho eseguito questo, funziona:

var firstTask = NSEntityDescription.insertNewObjectForEntityForName("Task", 
    inManagedObjectContext: managedObjectContext) as NSManagedObject 

firstTask.setPrimitiveValue("File my TPS reports", forKey: "name") 

var error: NSError? 

managedObjectContext.save(&error) 

posso anche andare nel database SQLite in uso dal simulatore iOS e confermare che la riga è stata aggiunta.

Tuttavia, quando si esegue lo stesso codice esattamente come sopra ma con as Task invece di as NSManagedObject, ottengo un incidente con il messaggio di errore Thread 1: EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0), associata alla var firstTask ... linea. Se continuo l'esecuzione, ottengo EXC_BAD_ACCESS e 0 misaligned_stack_error_ all'inizio di Thread 1 ogni volta che lo anticipo.

Perché questo cast potrebbe portare a tutto questo?

+0

di poter postare uno screenshot dello schermo del modello CoreData che mostra l'entità 'Task', con l'ispettore Entità vista aperta sulla destra? – Erik

+0

Grande commento. Grazie. Mi ha appena portato a una soluzione di lavoro. –

+0

qual è stata la soluzione? – DeveloperACE

risposta

45

Assicurarsi che il campo Nome classe è in realtà modulo .Task, dove modulo è il nome della vostra applicazione. Le classi CoreData in Swift sono namespace. In questo momento, il tuo oggetto viene estratto dal contesto come un oggetto NSManagedObject, non come un compito, quindi l'as-cast sta fallendo.

+0

Grazie per il suggerimento Ben. Ho appena provato a cambiarlo in 'come AppName.Task' e sembra che stia ottenendo lo stesso comportamento. Altre idee? Forse intendevi qualcos'altro? –

+4

Non importa. Ho funzionato ora. Il tuo suggerimento più la richiesta di SiLo mi ha aiutato a capire tutto. Avevo bisogno di usare 'AppName.Task' nel campo Classe nell'ispettore dell'entità modello Core Data. –

+1

Per favore, fai notare nella tua risposta che dovresti aggiungere AppName.Model nel file xcdatamodeld. Mi sono preso un po 'per capire. – Matt3o12

11

È necessario modificare il file Task.swift. L'aggiunta di @objc (Task) come di seguito

import CoreData 

@objc(Task) 
class Task: NSManagedObject { 
    @NSManaged var name: String 
} 

Penso che questo come un bug se il progetto non contiene alcun codice Objective-C. Tuttavia, è necessario aggiungere quella linea fino a quando non è stato risolto.

L'ho imparato da qui.

Youtube video at 11:45

5

Credo che solo cambiando il campo di classe nella .xcdatamodel non funziona più perché ho ancora avuto la seguente eccezione: Errore irreversibile: uso di initializer implementato 'init (entità: insertIntoManagedObjectContext :)' per la classe

Così, ho inserito questo codice nel mio classe personalizzata:

init(entity: NSEntityDescription!, 
    insertIntoManagedObjectContext context: NSManagedObjectContext!) { 
     super.init(entity: entity, insertIntoManagedObjectContext: context) 
} 

Improvvisamente, ha funzionato! NSManagedObject è ora scaricabile per la mia classe personalizzata. Non riesco davvero a capire perché questa sia la soluzione, ma funziona :)

1

Mi sono imbattuto in questo problema negli ultimi giorni e stranamente la soluzione che ha funzionato per me era una variante di quella sopra suggerita.

Ho aggiunto la dichiarazione @objc alle sottoclassi generate, ma ho rimosso qualsiasi prefisso del namespace nel nome della classe nel modello di oggetto (aveva un prefisso predefinito di "PRODUCT_MODULE_NAME." Dopo che le sottoclassi sono state generate). Ha funzionato.

2

Ho dovuto aggiungere @objc() e impostare la classe nell'interfaccia coredata. Nella finestra destra di CoreData, nell'area Entità, ci sono la casella di testo Nome e Classe. La classe non deve essere MSManagedObject, ma invece la classe. Ho creato un simple working example!

+1

il problema di trasmettere l'oggetto nsmanaged su custom, accade quando provi a farlo nella destinazione del test, non sul progetto principale, come nel tuo esempio. – KeranMarinov

28

Questo è anche frustrato se hai provato tutti i suggerimenti di cui sopra e non di loro lavorano per me !!

Quindi questo è ciò che funziona per me.

1- Selezionare il file xcdatamodeld

2- Assicurarsi che tutte le entità non ha nessun modulo nel "modello di dati ispettore", se si vede "Modello: corrente modulo di prodotto" ..clear è così sembra l'immagine allegata.

3- cancellare i tuoi App per cancellare i dati di base

4- Se ancora non funziona, cancellare i tuoi entità e rigenerarsi.

enter image description here

+1

Nel mio caso, in particolare, quello che mi mancava era l'aggiunta della classe stessa al posto del modulo. Grazie per aver pubblicato un video che mi ha reso chiaro questo. –

+0

Questa dovrebbe essere la risposta accettata .. nessuna delle altre risposte funziona. grazie @polarwar – Nookaraju

5

Un aggiornamento per @ Ben Gottlieb risposta sotto XCode 7.1 e Swift 2,0

  1. aggiungere @objc alla classe. Vedi la risposta di Owen Zhao. Il seguente è un esempio:
@objc 
class ImageRecordMO: NSManagedObject{ 
  1. Aprire il file .xcdatamodled.

  2. Selezionare la propria entità e fare clic sull'ispettore modello dati sul pannello di destra.

  3. Immettere il nome della classe, vedere la figura seguente

  4. Seleziona il tuo modulo per essere corrente modulo di prodotto, vedere la figura seguente.

enter image description here

+0

SÌ! Così ovvio! \ o/Mi rammarico di avere un solo voto da dare. – Epaga

4

Xcode 7 + Swift 2

Person.swift

@objc(Person) 
class Person: NSManagedObject { 
} 

modello dati

enter image description here

Poi basta chiamare

let person = NSEntityDescription.insertNewObjectForEntityForName("Person", inManagedObjectContext: self.managedObjectContext) as! Person