web-dev-qa-db-fra.com

executeFetchRequest: erreur irrécupérable: l'élément NSArray n'a pas pu correspondre au type d'élément Swift Array

Je teste Swift avec CoreData et j'ai créé le code suivant:

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)")

    }

}

Quand je cours:

Contact.execute()

Ensuite, le compilateur renvoie cette erreur:

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

quand j'essaie d'obtenir des valeurs de array:

 let firstContact = result[0] as Contact

Je suppose que le problème est dans executeFetchRequest. Sur Objective-c le type de retour de executeFetchRequest est une NSArray. Maintenant sur Swift le type de retour est un [AnyObject]?.

J'ai essayé de convertir le résultat [AnyObject]? en NSArray, mais Xcode a déclaré:

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

Qu'est-ce que je fais mal?

J'utilise: Xcode 6.0 (6A313) GM et OSX 10.9.4

Mettre à jour:
-----------

Si j'obtiens executeFetchRequest résultat sous la forme d'un tableau facultatif et que j'utilise [NSManagedObject] au lieu de [Contact], cela fonctionne. 

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:
-----------

Ce type de problème se produit lorsque les instances d'entité n'ont pas été chargées à l'aide de votre classe NSManagedObject. Cela se produit pour différentes raisons. Toutes se concentrent sur "Core Data n'a pas pu trouver la classe spécifiée pour cette entité sur la ligne de classe dans le modèle de données".

Parmi les possibilités:
- Vous avez spécifié le mauvais paquet pour votre classe Swift
- Vous avez oublié de spécifier la classe
- Vous avez mal orthographié le nom

Dans mon cas, j’ai oublié de spécifier la classe comme le montre POB dans sa réponse.

15
Sebastian

J'ai pu reproduire votre message d'erreur dans la console. Vous recevez ce message parce que vous n'avez pas correctement défini le nom de votre classe d'entité dans l'éditeur de modèle de données principal (voir l'image ci-dessous).

enter image description here

Une fois cela fait, vous pourrez utiliser votre code original avec Contact subClass. Vous pouvez en apprendre plus sur les données de base et les espaces de noms ici .

33
Imanou Petit

Dans mon cas, j'ai changé le module en tant que "Module de produit actuel" dans l'éditeur de modèle de données principal. Il a commencé à bien fonctionner pour moi.

 enter image description here

6
Danboz

Je pense que c'est une mauvaise idée de définir le préfixe de votre nom de cible comme this Parce que si vous souhaitez déplacer votre modèle dans une autre application ou changer le nom de la cible, vous devrez le modifier à nouveau.

Donc, il y a un autre moyen. Si vous regardez maintenant comment xcode génère des entités de données de base, @A_man a déclaré que vous deviez définir le module actuel dans editor et utiliser @objc () comme ceci:

import CoreData

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

Et le champ doit être facultatif car ils peuvent être nuls

0
Serg Dort

Vérifiez la classe et le module dans Entity à partir de l'inspecteur de modèles de données et définissez le nom de la classe comme nom d'entité et le module comme "Module produit actuel" Nom de la classe et module

0
Subhash