Bagaimana cara menyimpan Array ke CoreData?

93

Saya perlu menyimpan array saya ke Core Data.

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

Nilai-nilai di dalam larik itu, dan jumlah nilainya adalah variabel.

1. Apa yang saya nyatakan di dalam kelas NSManagedObject saya?

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. Apa yang saya nyatakan di dalam .xcdatamodel saya?

masukkan deskripsi gambar di sini

3. Bagaimana cara menyimpan ini di Entitas saya? (Saya menggunakan 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
sumber
Tidak ada "harus", desain DB terserah Anda, misalnya sejauh yang saya ketahui, Anda sebaiknya menggunakan tanggal atau format teks jika ini terbukti menjadi cara paling efisien untuk menyimpan data ini di aplikasi Anda.
A-Live
Jadi di dalam saya NSManagedObject: @NSManaged var values: [Double]apakah itu baik? Bisakah Anda memberi tahu saya jenis apa yang harus saya gunakan .xcdatamodeluntuk menyimpan ini?
Bartłomiej Semańczyk
Saya mungkin belum menjelaskannya dengan cukup jelas, cara Anda menanyakannya adalah tentang preferensi pribadi, tidak ada masalah nyata untuk dipecahkan. Jika Anda mencari cara untuk menggunakan relasi satu-ke-banyak, tambahkan informasi tentang apa yang telah Anda coba dan di mana Anda mengalami masalah. Jika Anda memahami setiap solusi yang disebutkan oleh Anda dan mencari solusi yang paling efisien - buat daftar kriteria efisiensi Anda dan jelaskan kasus penggunaan. Jika karena alasan tertentu Anda mengalami kesulitan dalam memahami berbagai jenis relasi atau tidak ingin menggunakan relasi sama sekali - katakan secara langsung.
A-Live
Saya memperbarui pertanyaan
Bartłomiej Semańczyk
Nah, itu pertanyaan yang layak, saya telah menambahkan tag MagicalRecord untuk Anda, sayangnya saya tidak berpengalaman di bidang ini dan semoga seseorang yang akan dapat membantu Anda lebih baik dari titik ini.
A-Live

Jawaban:

180

Ok, saya melakukan penelitian dan pengujian. Menggunakan tipe Transformable , solusinya sederhana:

1. Apa yang saya nyatakan di dalam kelas NSManagedObject saya?

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

2. Apa yang saya nyatakan di dalam .xcdatamodel saya?

Transformable tipe data.

3. Bagaimana cara menyimpan ini di Entitas saya?

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

“Anda dapat menyimpan NSArray atau NSDictionary sebagai atribut yang dapat diubah. Ini akan menggunakan NSCoding untuk membuat serial larik atau kamus ke atribut NSData (dan deserialisasi yang sesuai saat diakses) "- Sumber

Atau Jika Anda ingin mendeklarasikannya sebagai Data Biner, baca artikel sederhana ini :

Bartłomiej Semańczyk
sumber
Kerja bagus, jawabannya sepertinya layak diberi tanda centang hijau demi penyelesaian.
A-Live
3
Juga bekerja dengan [NSString]untuk array string
Daisy R.
Apakah mungkin menambahkan predikat saat mengambil dari data inti?
Satyam
5
Dalam kasus saya, saya mencoba menggunakan array Strings dan tidak berhasil
allemattio
bagaimana Anda melakukan ini dengan 3 cara cepat?
Martian2049
98

Swift 3 Karena kami tidak lagi memiliki file implementasi seperti pada Swift 3, yang harus kami lakukan adalah membuka file xcdatamodeld, pilih entitas dan atribut yang diinginkan (dalam contoh ini disebut nilai). Setel sebagai dapat diubah dan kelas khususnya menjadi [Double]. Sekarang gunakan sebagai array normal.

Mengatur kelas kustom ke array Double

Hola Soy Edu Feliz Navidad
sumber
Apakah mungkin untuk mendefinisikan kelas kustom sebagai [[String: Any]]? Array kamus
BergP
Secara teoritis itu harus dapat diterima, namun saya belum pernah mencoba.
Hola Soy Edu Feliz Navidad
2
Anda selalu dapat mengatur codegen ke Manual / Tidak Ada dan menulis kelas model Data Inti Anda sendiri.
Skema
14

Ubah Array ke 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)")
}

Pilih Data Biner

Ubah NSData ke 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)")
}

Sebagai Contoh: https://github.com/kkvinokk/Event-Tracker

Vinoth Anandan
sumber
1
Menggunakan NSData memang lebih masuk akal dan lebih sederhana.
GeneCode
2
Jika Anda ingin menambahkan predikat ke atribut itu, itu mungkin tidak berhasil.
Satyam
6

Jika menjaganya tetap sederhana dan menyimpan array sebagai string

Coba ini:

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

Untuk tipe data lainnya masing-masing:

// 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
sumber
Solusi Anda menghemat banyak waktu saya
Kishore Kumar
Saya tidak yakin mengapa, tetapi tidak ada solusi yang berhasil untuk saya. Saya mencoba solusi Anda untuk menyimpan data array string di Core Data dan mengambilnya, lalu mendekodekannya ke array string sesudahnya, tetapi masih tidak berfungsi. Ada saran?
Tyler Cheek
3

Jadikan jenis atribut entitas sebagai "Data Biner"

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

Dapatkan kembali larik asli sebagai:

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

Itu saja.

Avijit Nagare
sumber
1

Kode berikut berfungsi bagi saya untuk menyimpan array JSON di 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
sumber