Como salvar Array em CoreData?


91

Preciso salvar meu array em Core Data.

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

Os valores dentro dessa matriz e o número de valores são variáveis.

1. O que declaro dentro da minha 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. O que declaro dentro do meu .xcdatamodel?

insira a descrição da imagem aqui

3. Como faço para salvar isso na minha entidade? (Eu uso MagicalRecord)

let statistics = (PBOStatistics.MR_createInContext(context) as! PBOStatistics)
statistics.values = [8, 17.7, 18, 21, 0, 0, 34] //is it enough?

Não há "deveria", o design do banco de dados é com você, por exemplo, no que me diz respeito, você também pode usar datas ou formato de texto se essa for a maneira mais eficiente de armazenar esses dados em seu aplicativo.
A-Live

Então dentro do meu NSManagedObject: @NSManaged var values: [Double]isso é bom? Você pode me dizer que tipo devo usar .xcdatamodelpara salvar isso?
Bartłomiej Semańczyk

Posso não ter deixado claro o suficiente, a maneira como você pergunta é sobre a preferência pessoal, não há nenhum problema real para resolver. Se você está procurando alguma maneira de usar relações um para muitos, adicione as informações sobre o que você tentou e onde teve um problema. Se você entende cada uma das soluções mencionadas por você e está procurando a mais eficiente - liste seus critérios de eficiência e descreva os casos de uso. Se por alguma razão você está tendo problemas para entender diferentes tipos de relações ou não quer usar relações de forma alguma - diga isso diretamente.
A-Live

Eu atualizei a pergunta
Bartłomiej Semańczyk

Essa é uma pergunta decente, adicionei uma tag MagicalRecord para você, infelizmente não tenho experiência nessa área e espero que alguém que tenha possa ajudá-lo melhor a partir deste ponto.
A-Live

Respostas:


177

Ok, fiz algumas pesquisas e testes. Usando o tipo Transformable , a solução é simples:

1. O que declaro dentro da minha classe NSManagedObject?

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

2. O que declaro dentro do meu .xcdatamodel?

Transformable tipo de dados.

3. Como faço para salvar isso na minha entidade?

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

“Você pode armazenar um NSArray ou um NSDictionary como um atributo transformável. Isso usará o NSCoding para serializar a matriz ou dicionário para um atributo NSData (e desserializar apropriadamente ao acessar) ”- Fonte

Ou se você deseja declará-lo como dados binários , leia este artigo simples :


Bom trabalho, a resposta parece valer uma marca de verificação verde para fins de conclusão.
A-Live

2
Também funciona com [NSString]uma série de strings
Daisy R.

É possível adicionar predicado durante a busca de dados principais?
Satyam

3
No meu caso, estou tentando usar um array de Strings e não funciona
allemattio

como você faria isso em 3 maneiras rápidas?
Martian2049

94

Swift 3 Como não temos mais os arquivos de implementação a partir do Swift 3, o que temos que fazer é ir até o arquivo xcdatamodeld, selecionar a entidade e o atributo desejado (neste exemplo é chamado de valores). Defina-o como transformável e sua classe personalizada como [Double]. Agora use-o como um array normal.

Configurando a classe personalizada para array de Double


É possível definir a classe personalizada como [[String: Any]]? Uma série de dicionários
BergP

Teoricamente, deveria ser aceitável, mas nunca tentei.
Hola Soy Edu Feliz Navidad

2
Você sempre pode definir codegen como Manual / Nenhum e escrever sua própria classe de modelo de dados principais.
Schemetrical

14

Converter Array em 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)")
}

Selecione Dados Binários

Converter NSData em 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)")
}

Por exemplo: https://github.com/kkvinokk/Event-Tracker


1
Usar NSData de fato faz mais sentido e mais simples.
GeneCode

2
Se você quiser adicionar um predicado a esse atributo, pode não funcionar.
Satyam

5

Se for simples e armazenar um array como uma string

Experimente isto:

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

Para outros tipos de dados, respectivamente:

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

Sua solução economizou muito tempo
Kishore Kumar

Não sei por que, mas nenhuma dessas soluções está funcionando para mim. Tentei sua solução de armazenar os dados da matriz de string em Core Data e recuperá-los e, em seguida, decodificá-los em uma matriz de string, mas ainda não está funcionando. Algum conselho?
Tyler Cheek

3

Faça o tipo de atributo de entidade como "Dados binários"

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

Recupere a matriz original como:

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

Isso é tudo.


1

O seguinte código funciona para mim para armazenar array de JSON em 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")
    }

}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.