Comment enregistrer Array dans CoreData?

91

J'ai besoin de sauvegarder ma matrice dans Core Data.

let array = [8, 17.7, 18, 21, 0, 0, 34]

Les valeurs à l'intérieur de ce tableau et le nombre de valeurs sont variables.

1. Que dois-je déclarer dans ma classe NSManagedObject?

class PBOStatistics: NSManagedObject, Equatable {
    @NSManaged var date: NSDate
    @NSManaged var average: NSNumber
    @NSManaged var historicAverage: NSNumber
    @NSManaged var total: NSNumber
    @NSManaged var historicTotal: NSNumber
    @NSManaged var ordersCount: NSNumber
    @NSManaged var historicOrdersCount: NSNumber
    @NSManaged var values: [Double]  //is it ok?

    @NSManaged var location: PBOLocation

}

2. Que dois-je déclarer dans mon .xcdatamodel?

entrez la description de l'image ici

3. Comment puis-je enregistrer cela dans mon entité? (J'utilise MagicalRecord)

let statistics = (PBOStatistics.MR_createInContext(context) as! PBOStatistics)
statistics.values = [8, 17.7, 18, 21, 0, 0, 34] //is it enough?
Bartłomiej Semańczyk
la source
Il n'y a pas de "devrait", la conception de la base de données dépend de vous, par exemple en ce qui me concerne, vous pouvez aussi bien utiliser des dates ou un format texte si cela s'avère être le moyen le plus efficace de stocker ces données dans votre application.
A-Live
Donc à l'intérieur de mon NSManagedObject: @NSManaged var values: [Double]est-ce bon? Pouvez-vous me dire quel type dois-je utiliser .xcdatamodelpour enregistrer cela?
Bartłomiej Semańczyk
Je n'ai peut-être pas été assez clair, la façon dont vous posez les questions concerne les préférences personnelles, il n'y a pas de réel problème à résoudre. Si vous recherchez un moyen d'utiliser les relations un-à-plusieurs, ajoutez les informations sur ce que vous avez essayé et sur les points où vous avez rencontré un problème. Si vous comprenez chacune des solutions que vous avez mentionnées et que vous recherchez la plus efficace, indiquez vos critères d'efficacité et décrivez les cas d'utilisation. Si, pour une raison quelconque, vous avez du mal à comprendre différents types de relations ou si vous ne voulez pas du tout utiliser de relations, dites-le directement.
A-Live
J'ai mis à jour la question
Bartłomiej Semańczyk
Maintenant que c'est une question décente, j'ai ajouté une balise MagicalRecord pour vous, malheureusement je n'ai pas d'expérience dans ce domaine et j'espère que quelqu'un qui sera en mesure de mieux vous aider à partir de ce point.
A-Live

Réponses:

177

Ok, j'ai fait des recherches et des tests. Utilisation de transformable type , la solution est simple:

1. Que dois-je déclarer dans ma classe NSManagedObject?

@NSManaged var values: [NSNumber]  //[Double] also works

2. Que dois-je déclarer dans mon .xcdatamodel?

Transformable Type de données.

3. Comment puis-je enregistrer cela dans mon entité?

statistics!.values = [23, 45, 567.8, 123, 0, 0] //just this

«Vous pouvez stocker un NSArray ou un NSDictionary en tant qu'attribut transformable. Cela utilisera le NSCoding pour sérialiser le tableau ou le dictionnaire en un attribut NSData (et le désérialiser de manière appropriée lors de l'accès) »- Source

Ou si vous souhaitez le déclarer en tant que données binaires, lisez cet article simple :

Bartłomiej Semańczyk
la source
Bon travail, la réponse semble valoir une coche verte pour le plaisir de terminer.
A-Live
2
Fonctionne également avec [NSString]pour un tableau de chaînes
Daisy R.
Est-il possible d'ajouter un prédicat lors de la récupération des données de base?
Satyam
3
Dans mon cas, j'essaie d'utiliser un tableau de chaînes et cela ne fonctionne pas
allemattio
comment feriez-vous cela de manière rapide 3?
Martian2049
94

Swift 3 Comme nous n'avons plus les fichiers d'implémentation à partir de Swift 3, ce que nous devons faire est d'aller dans le fichier xcdatamodeld, sélectionner l'entité et l'attribut souhaité (dans cet exemple, cela s'appelle values). Définissez-le comme transformable et sa classe personnalisée sur [Double]. Maintenant, utilisez-le comme un tableau normal.

Définition d'une classe personnalisée sur un tableau de Double

Hola Soy Edu Feliz Navidad
la source
Est-il possible de définir une classe personnalisée comme [[String: Any]]? Un tableau de dictionnaires
BergP
Théoriquement, cela devrait être acceptable, mais je n'ai jamais essayé.
Hola Soy Edu Feliz Navidad
2
Vous pouvez toujours définir codegen sur Manual / None et écrire votre propre classe de modèle Core Data.
schématique
14

Convertir un tableau en NSData

let appDelegate =
    UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entity =  NSEntityDescription.entityForName("Device",
                                                inManagedObjectContext:managedContext)
let device = NSManagedObject(entity: entity!,
                             insertIntoManagedObjectContext: managedContext)
let data = NSKeyedArchiver.archivedDataWithRootObject(Array)

device.setValue(data, forKey: "dataOfArray")
do {
    try managedContext.save()
    devices.append(device)
} catch let error as NSError  {
    print("Could not save \(error), \(error.userInfo)")
}

Sélectionnez les données binaires

Convertir NSData en tableau

let appDelegate =
    UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "Device")

do {
    let results =
        try managedContext.executeFetchRequest(fetchRequest)

    if results.count != 0 {

        for result in results {

                let data = result.valueForKey("dataOfArray") as! NSData
                let unarchiveObject = NSKeyedUnarchiver.unarchiveObjectWithData(data)
                let arrayObject = unarchiveObject as AnyObject! as! [[String: String]]
                Array = arrayObject
        }

    }

} catch let error as NSError {
    print("Could not fetch \(error), \(error.userInfo)")
}

Par exemple: https://github.com/kkvinokk/Event-Tracker

Vinoth Anandan
la source
1
L'utilisation de NSData est en effet plus logique et plus simple.
GeneCode
2
Si vous souhaitez ajouter un prédicat à cet attribut, cela peut ne pas fonctionner.
Satyam
5

Si vous restez simple et stockez un tableau sous forme de chaîne

Essaye ça:

// Array of Strings
let array: [String] = ["red", "green", "blue"]
let arrayAsString: String = array.description
let stringAsData = arrayAsString.data(using: String.Encoding.utf16)
let arrayBack: [String] = try! JSONDecoder().decode([String].self, from: stringAsData!)

Pour les autres types de données respectivement:

// Set of Doubles
let set: Set<Double> = [1, 2.0, 3]
let setAsString: String = set.description
let setStringAsData = setAsString.data(using: String.Encoding.utf16)
let setBack: Set<Double> = try! JSONDecoder().decode(Set<Double>.self, from: setStringAsData!)
Alexey Chekanov
la source
Votre solution m'a fait gagner beaucoup de temps
Kishore Kumar
Je ne sais pas pourquoi, mais aucune de ces solutions ne fonctionne pour moi. J'ai essayé votre solution consistant à stocker les données du tableau de chaînes dans Core Data et à les récupérer, puis à les décoder en tableau de chaînes par la suite, mais cela ne fonctionne toujours pas. Aucun conseil?
Tyler Cheek
3

Définir le type d'attribut d'entité comme "Données binaires"

NSData *arrayData = [NSKeyedArchiver archivedDataWithRootObject:TheArray];
myEntity.arrayProperty = arrayData;
[self saveContext]; //Self if we are in the model class

Récupérez la matrice d'origine comme:

NSMutableArray *array = [NSKeyedUnarchiver unarchiveObjectWithData:anEntity.arrayProperty];

C'est tout.

Avijit Nagare
la source
1

Le code suivant fonctionne pour moi pour stocker un tableau de JSON dans CoreData

func saveLocation(model: [HomeModel],id: String){

    let newUser = NSEntityDescription.insertNewObject(forEntityName: "HomeLocationModel", into: context)

    do{
        var dictArray = [[String: Any]]()
        for i in 0..<model.count{
            let dict = model[i].dictionaryRepresentation()
            dictArray.append(dict)
        }
        let data = NSKeyedArchiver.archivedData(withRootObject: dictArray)
        newUser.setValue(data, forKey: "locations")
        newUser.setValue(id, forKey: "id")
        try context.save()
    }catch {
       print("failure")
    }

}
Rahul Gusain
la source