RealmSwift: converti i risultati in Swift Array


143

Cosa voglio implementare:

class func getSomeObject() -> [SomeObject]? {
    let objects = Realm().objects(SomeObject)

    return objects.count > 0 ? objects : nil
}

Come posso restituire l'oggetto come [SomeObject]invece se Results?

Risposte:


379

Strano, la risposta è molto semplice. Ecco come lo faccio:

let array = Array(results) // la fin

non restituisce un NSArray?
— martedì

2
@thesummersign Realm è cambiato molto di recente, ma una cosa è certa: il codice sopra restituisce uno Swift Arraycostruito con l'iteratore dei risultati.
— Mazyod,

4
Restituisce il numero zero di entità (iniziale)
— Nik Kov,

2
Concordo con @NikKov, sembra che stia tornando a zero l'entità; (
— Jon

2
@Jon Come vedi che sono nulli? Sembra che siano pigri, quando li guardi fermati in un punto di debug sembrano vuoti ma se li stampi accede a loro e mostra il valore corretto (per me).
— Geremia

31

Se devi assolutamente convertirti Resultsin Array, tieni presente che c'è un sovraccarico di prestazioni e memoria, poiché Resultsè pigro. Ma puoi farlo in una riga, come results.map { $0 }in swift 2.0 (o map(results) { $0 }in 1.2).


Quale versione di Realm?
— Sahil Kapoor,

31
Questa conversione non è una necessità se non vuoi perdere la dipendenza da Realm in troppe classi del tuo progetto?
— Marcin Kuptel,

15
map { $0 }tornerà LazyMapRandomAccessCollectionin Swift 3, quindi la risposta di @Mazyod è migliore.
— Legoless,

@MarcinKuptel sì, questo è esattamente il problema che ho riscontrato. Sono stato in grado di sottrarre il modello del regno creando una struttura conforme a un protocollo, ed è questa astrazione del protocollo che definisco nelle mie firme nella mia base di codice. Tuttavia, a volte ho bisogno di convertirmi in un array, c'è un modo per avere una raccolta pigra del mio protocollo astratto in modo che converta solo nella struttura al momento dell'accesso?
— Pavan,

20

Ho trovato una soluzione Estensione creata sui risultati.

extension Results {
    func toArray<T>(ofType: T.Type) -> [T] {
        var array = [T]()
        for i in 0 ..< count {
            if let result = self[i] as? T {
                array.append(result)
            }
        }

        return array
    }
}

e usando come

class func getSomeObject() -> [SomeObject]? {
    let objects = Realm().objects(SomeObject).toArray(SomeObject) as [SomeObject]

    return objects.count > 0 ? objects : nil
}

4
for var i = 0; i < count; i++ dovrebbe essere sostituito confor i in 0 ..< count
— Sal

1
Quanto sopra è un modo molto confuso di scrivere l'estensione: extension Results {var array: [Element] {return self.map {$ 0}}}
— Giles

10

Con Swift 4.2 è semplice come un'estensione:

extension Results {
    func toArray() -> [Element] {
      return compactMap {
        $0
      }
    }
 }

Tutte le informazioni generiche necessarie sono già una parte delle Resultsquali estendiamo.


8

Questo è un altro modo di convertire Resultsin array con un'estensione con Swift 3 in una sola riga.

extension Results {
    func toArray() -> [T] {
        return self.map { $0 }
    }
}

Per Swift 4 e Xcode 9.2

extension Results {
    func toArray<T>(type: T.Type) -> [T] {
        return flatMap { $0 as? T }
    }
}

Con Xcode 10 flatMap è deprecato è possibile utilizzare compactMapper la mappatura.

extension Results {
    func toArray<T>(type: T.Type) -> [T] {
        return compactMap { $0 as? T }
    }
}

Mentre sto usando questo codice nella versione 9.2 di XCode, mi mostra l'uso del tipo non dichiarato 'T'
— Bhavesh Dhaduk,

Aggiornata la mia risposta, puoi verificarla.
— abdullahselek,

Per Xcode 10 e versioni successive è possibile utilizzare compactMap anziché flatMap per evitare l'avviso.
— Metodij Zdravkin,

6

Swift 3

extension Results {
    func toArray<T>(ofType: T.Type) -> [T] {
        var array = [T]()
        for i in 0 ..< count {
            if let result = self[i] as? T {
                array.append(result)
            }
        }

        return array
    }
}

uso

class func getSomeObject() -> [SomeObject]? {
   let defaultRealm = try! Realm()
    let objects = defaultRealm.objects(SomeObject.self).toArray(ofType : SomeObject.self) as [SomeObject]

    return objects.count > 0 ? objects : nil
}

Alternativa: usare generici

class func getSomeObject() -> [T]? {
        let objects = Realm().objects(T.self as! Object.Type).toArray(ofType : T.self) as [T]

        return objects.count > 0 ? objects : nil
}

4

non è una buona idea convertire i risultati in array, perché i risultati sono pigri. Ma se hai bisogno di provare questo:

func toArray<T>(ofType: T.Type) -> [T] {
    return flatMap { $0 as? T }
}

ma il modo migliore è passare i risultati ovunque tu abbia bisogno. Inoltre, puoi convertire i risultati in Elenco anziché in Matrice.

List(realm.objects(class))

se la prima funzione non funziona puoi provare questa:

var refrenceBook:[RefrenceProtocol] = []
let faceTypes = Array(realm.objects(FaceType))
refrenceBook = faceTypes.map({$0 as FaceType})

Dopo aver aggiornato RealmSwift alla 3.4.0, l'elenco non accetta argomenti. Come convertire un array in Elenco in questo caso? Qualche idea?
— Nishu_Priya,

1
@NishuPriya qui puoi lasciare myList = List <Person> () myList.append (objectsIn: realm.objects (Person.self))
— Nosov Pavel

2

Non sono sicuro se esiste un modo efficace per farlo.

Ma puoi farlo creando un array Swift e aggiungendolo nel ciclo.

class func getSomeObject() -> [SomeObject]? {
    var someObjects: [SomeObject] = []
    let objects = Realm().objects(SomeObject)
    for object in objects{
        someObjects += [object]
    }
    return objects.count > 0 ? someObjects : nil
}

Se ritieni che sia troppo lento. Ti consiglio di passare Resultsdirettamente all'oggetto Realm .


Ho fatto qualcosa del genere solo creando un'estensione su Resules. Ho pubblicato il codice come risposta. Grazie :)
— Sahil Kapoor,

si. Lo farei anche io.
— nRewik,

2
extension Results {
    var array: [Element]? {
        return self.count > 0 ? self.map { $0 } : nil
    }
}

Quindi, puoi usare come:

Realm().objects(SomeClass.self).filter("someKey ENDSWITH %@", "sth").array

2

Soluzione per Swift 4, Realm 3

extension Results {
    func toArray<T>(ofType: T.Type) -> [T] {
        let array = Array(self) as! [T]
        return array
    }
}

Ora la conversione può essere eseguita come di seguito

let array = Realm().objects(SomeClass).toArray(ofType: SomeClass.self)

2
extension Results {
    func materialize() -> [Element] {
        return Array(self)
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.