Wie speichere ich Array in CoreData?

90

Ich muss mein Array in Core Data speichern.

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

Die Werte in diesem Array und die Anzahl der Werte sind variabel.

1. Was deklariere ich in meiner NSManagedObject-Klasse?

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. Was deklariere ich in meinem .xcdatamodel?

Geben Sie hier die Bildbeschreibung ein

3. Wie speichere ich dies in meiner Entität? (Ich benutze 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
quelle
Es gibt kein "sollte", das DB-Design liegt bei Ihnen, z. B. können Sie meines Erachtens auch Datums- oder Textformate verwenden, wenn sich dies als die effizienteste Methode zum Speichern dieser Daten in Ihrer Anwendung herausstellt.
A-Live
Also in meinem NSManagedObject: @NSManaged var values: [Double]ist es gut? Können Sie mir sagen, in welchem ​​Typ ich .xcdatamodeldas speichern soll?
Bartłomiej Semańczyk
Ich habe es vielleicht nicht klar genug gemacht. Die Art und Weise, wie Sie es fragen, hängt von persönlichen Vorlieben ab. Es gibt kein wirkliches Problem, das gelöst werden muss. Wenn Sie nach einer Möglichkeit suchen, Eins-zu-Viele-Beziehungen zu verwenden, fügen Sie die Informationen darüber hinzu, was Sie versucht haben und wo Sie ein Problem hatten. Wenn Sie jede der von Ihnen genannten Lösungen verstehen und nach der effizientesten suchen, listen Sie Ihre Effizienzkriterien auf und beschreiben Sie die Anwendungsfälle. Wenn Sie aus irgendeinem Grund Probleme haben, verschiedene Arten von Beziehungen zu verstehen, oder überhaupt keine Beziehungen verwenden möchten, sagen Sie es direkt.
A-Live
Ich habe die Frage aktualisiert
Bartłomiej Semańczyk
Nun, das ist eine anständige Frage. Ich habe ein MagicalRecord-Tag für Sie hinzugefügt. Leider habe ich in diesem Bereich keine Erfahrung und hoffe, dass jemand, der es ist, Ihnen von diesem Punkt aus besser helfen kann.
A-Live

Antworten:

175

Ok, ich habe recherchiert und getestet. Mit dem transformierbaren Typ ist die Lösung einfach:

1. Was deklariere ich in meiner NSManagedObject-Klasse?

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

2. Was deklariere ich in meinem .xcdatamodel?

Transformable Datentyp.

3. Wie speichere ich dies in meiner Entität?

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

„Sie können ein NSArray oder ein NSDictionary als transformierbares Attribut speichern. Dadurch wird die NSCoding verwendet, um das Array oder Wörterbuch in ein NSData-Attribut zu serialisieren (und es beim Zugriff entsprechend zu deserialisieren). ”- Quelle

Oder Wenn Sie es als Binärdaten deklarieren möchten, lesen Sie diesen einfachen Artikel :

Bartłomiej Semańczyk
quelle
Gute Arbeit, die Antwort scheint ein grünes Häkchen wert zu sein.
A-Live
2
Funktioniert auch mit [NSString]für eine Reihe von Zeichenfolgen
Daisy R.
Ist es möglich, beim Abrufen von Kerndaten ein Prädikat hinzuzufügen?
Satyam
3
In meinem Fall versuche ich, ein Array von Strings zu verwenden und es funktioniert nicht
allemattio
Wie würden Sie dies auf schnelle Weise tun?
Martian2049
93

Swift 3 Da wir ab Swift 3 keine Implementierungsdateien mehr haben, müssen wir zur xcdatamodeld-Datei gehen, die Entität und das gewünschte Attribut auswählen (in diesem Beispiel heißt es Werte). Setzen Sie es als transformierbar und seine benutzerdefinierte Klasse auf [Double]. Verwenden Sie es jetzt als normales Array.

Festlegen der benutzerdefinierten Klasse auf das Array Double

Hola Soja Edu Feliz Navidad
quelle
Ist es möglich, eine benutzerdefinierte Klasse als [[String: Any]] zu definieren? Eine Reihe von Wörterbüchern
BergP
Theoretisch sollte es akzeptabel sein, aber ich habe es nie versucht.
Hola Soja Edu Feliz Navidad
2
Sie können codegen jederzeit auf Manual / None setzen und Ihre eigene Core Data-Modellklasse schreiben.
Schema
14

Array in NSData konvertieren

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

Wählen Sie Binärdaten

Konvertieren Sie NSData in Array

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

Zum Beispiel: https://github.com/kkvinokk/Event-Tracker

Vinoth Anandan
quelle
1
Die Verwendung von NSData ist in der Tat sinnvoller und einfacher.
GeneCode
2
Wenn Sie diesem Attribut ein Prädikat hinzufügen möchten, funktioniert es möglicherweise nicht.
Satyam
5

Wenn Sie es einfach halten und ein Array als Zeichenfolge speichern

Versuche dies:

// 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!)

Für andere Datentypen:

// 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
quelle
Ihre Lösung hat mir viel Zeit gespart
Kishore Kumar
Ich bin mir nicht sicher warum, aber keine dieser Lösungen funktioniert für mich. Ich habe versucht, die Daten des String-Arrays in Core Data zu speichern, abzurufen und anschließend in ein String-Array zu dekodieren, aber es funktioniert immer noch nicht. Irgendein Rat?
Tyler Cheek
3

Machen Sie den Entitätsattributtyp zu "Binärdaten".

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

Ruft das ursprüngliche Array wie folgt ab:

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

Das ist alles.

Avijit Nagare
quelle
1

Der folgende Code funktioniert für mich, um ein Array von JSON in CoreData zu speichern

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
quelle