2014-09-17 11 views
13

Ich bin mit Coredata schnellen Testen und ich erstellt den folgenden Code:executeFetchRequest throw fatalen Fehler: NSArray Element konnte das Swift Array Elementtyp entsprechen

import UIKit 
import CoreData 

class Contact: NSManagedObject { 

    @NSManaged var name: String 
    @NSManaged var email: String 

    class func execute(){ 
     let appDel:AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate) 
     let context:NSManagedObjectContext = appDel.managedObjectContext! 

     let entityDescripition = NSEntityDescription.entityForName("Contact", inManagedObjectContext: context) 
     let contact = Contact(entity: entityDescripition!, insertIntoManagedObjectContext: context) 

     contact.name = "john Apleesee" 
     contact.email = "[email protected]" 

     context.save(nil) 

     let fetch:NSFetchRequest = NSFetchRequest(entityName: "Contact") 
     var result = context.executeFetchRequest(fetch, error: nil) as [Contact] 

     let firstContact = result[0] as Contact // <<-- error ! 

     println("\(firstContact.name)") 
     println("\(firstContact.email)") 

    } 

} 

Wenn ich laufen:

Contact.execute() 

dann werfen die Compiler diesen Fehler:

fatal error: NSArray element failed to match the Swift Array Element type 

wenn ich versuche, Werte von Array zu erhalten:

let firstContact = result[0] as Contact 

Ich denke, das Problem ist in executeFetchRequest. Unter Objective-c ist der Rückgabetyp executeFetchRequest ein NSArray. Jetzt auf Swift der Rückgabetyp ist ein [AnyObject]?.

Ich versuchte, das [AnyObject]? Ergebnis NSArray zu werfen, aber Xcode sagte:

Cannot convert the expression's type '[AnyObject]?' to type 'NSArray' 

Was mache ich falsch?

Ich verwende: Xcode 6.0 (6A313) GM und OSX 10.9.4

Update:
-----------

Wenn Ich bekomme executeFetchRequest Ergebnis als ein optionales Array und verwenden Sie [NSManagedObject] anstelle von [Contact] es funktioniert.

if let result: [NSManagedObject]? = context.executeFetchRequest(fetch, error: nil) as? [NSManagedObject] { 

     let firstContact: NSManagedObject = result![0] 

     let name = firstContact.valueForKey("name") as String 
     let email = firstContact.valueForKey("email") as String 

     println("\(name)") 
     println("\(email)") 
    } 

Update2:
-----------

Diese Art von Problem tritt auf, wenn Instanzen Entität nicht geladen werden hat Ihre NSManagedObject Klasse. Es gibt verschiedene Gründe, warum dies der Fall ist. Alle konzentrieren sich auf "Core Data konnte die Klasse, die Sie für diese Entität in der Klassenzeile im Datenmodell angegeben haben, nicht finden."

Unter den Möglichkeiten:
- Sie haben das falsche Paket für Ihre Swift-Klasse angegeben
- Sie haben vergessen, die Klasse zu spezifizieren
- Sie falsch geschriebene Namen

In meinem Fall wurde ich vergessen, die Klasse zu spezifizieren wie POB in ihrer Antwort zeigt.

+0

den Klassennamen als Entity-Name und Modul als 'Current Product Module' gesetzt Warum Sie den '-execute gesetzt hat:' Methode, führt ein 'NSFetchRequest' in Ihrer 'NSManagedObject'-Unterklasse? –

+0

Ich habe es aus Gründen der Einfachheit gemacht. Eine einfache Möglichkeit, das Problem hier zu zeigen. – Sebastian

+0

Haben Sie versucht, mit 'lassen Kontakt = NSEntityDescription.insertNewObjectForEntityForName ("Contact", inManagedObjectContext: Kontext) als Contact' statt' lassen contact = Kontakt (Einheit: entityDescripition !, insertIntoManagedObjectContext: context) '? –

Antwort

32

Ich konnte Ihre Fehlermeldung in der Konsole reproduzieren. Sie erhalten diese Meldung, weil Sie den Namen Ihrer Entitätsklasse im Core Data Model Editor nicht richtig festgelegt haben (siehe Abbildung unten).

enter image description here

Ist das erledigt, können Sie Ihre Original-Code mit Contact Subklasse verwenden. Sie können mehr über Core Data und Namespaces here erfahren.

+1

funktioniert wie ein Charme! vielen Dank! :) – Sebastian

+0

Lebensretter! .... –

+0

in dieser Klasse Feld, kann ich nicht hinzufügen „“ –

0

Ich denke, Ihr Problem ist, dass executeFetchRequest gibt ein optionales Array, kein Array zurück. Sie müssen es auspacken.

if let result: [Contact]? = context.executeFetchRequest(fetch, error: nil) as? [Contact] { 

    let firstContact = result[0] 

    println("/(firstContact.name)") 
    println("/(firstContact.email)") 
} 
+0

Danke für die Antwort Surrey! es war nicht mit Kontakt zu arbeiten, aber Wenn ich NSManageObject statt Kontakt läuft es. fragen sie mich nicht, warum! :) – Sebastian

3

In meinem Fall änderte ich das Modul als „Aktuelle Produktmodul“ innerhalb Core Data Modell Editor.It begann für mich gut funktioniert. enter image description here

0

Ich denke, seine schlechte Idee, wie this Präfix Ihres Ziel Namen einzustellen Denn wenn Sie Ihr Modell in andere App oder Änderung targer Namen, den Sie es mit wechselnden wieder

werden am Ende bewegen mag

Es gibt also einen anderen Weg. Wenn man sich anschaut, wie Xcode erzeugt nun Entitäten Kerndaten, wie @A_man gesagt, Sie aktuelle Modul in Editor und verwenden @objc() wie diese setzen müssen:

import CoreData 

@objc(Contact) 
class Contact: NSManagedObject { 
    @NSManaged var name: String? 
    @NSManaged var email: String? 
} 

Und Feld optional sein muss, weil sie sein können nil

Verwandte Themen