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.