RealmSwift: Convierta los resultados a Swift Array


143

Lo que quiero implementar:

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

    return objects.count > 0 ? objects : nil
}

¿Cómo puedo devolver un objeto como [SomeObject]si en su lugar Results?

Respuestas:


379

Extraño, la respuesta es muy sencilla. Así es como lo hago:

let array = Array(results) // la fin

¿No devuelve un NSArray?
thesummersign

2
@thesummersign Realm ha cambiado mucho recientemente, pero una cosa es segura: el código anterior devuelve un Swift Arrayconstruido con el iterador de resultados.
Mazyod

44
Devuelve nulo vars de la entidad (inicial)
Nik Kov

2
Estoy de acuerdo con @NikKov, parece estar volviendo nulos en la entidad; (
Jon

2
@ Jon ¿Cómo ves que son nulos? Parece que, dado que son vagos, cuando los mira detenidos en un punto de depuración, aparecen vacíos, pero si los imprime, accede a ellos y muestra el valor correcto (para mí).
Jeremías

31

Si es absolutamente necesario convertir Resultsa Array, tenga en cuenta que hay una sobrecarga de rendimiento y la memoria, ya que Resultses perezoso. Pero puede hacerlo en una línea, como results.map { $0 }en swift 2.0 (o map(results) { $0 }en 1.2).


¿Qué versión de Realm?
Sahil Kapoor

31
¿No es necesaria esta conversión si no quieres filtrar la dependencia de Realm a demasiadas clases en tu proyecto?
Marcin Kuptel

15
map { $0 }regresará LazyMapRandomAccessCollectionen Swift 3, por lo que la respuesta de @Mazyod es mejor.
Legoless

@MarcinKuptel sí, ese es exactamente el problema que encontré. He podido abstraer el modelo de reino creando una estructura que se ajusta a un protocolo, y es esta abstracción de protocolo la que defino en mis firmas en mi base de código. Sin embargo, a veces necesito convertir a una matriz, ¿hay alguna manera de tener una colección diferida de mi protocolo abstraído para que solo se convierta a la estructura en el momento del acceso?
Pavan

20

Encontré una solución. Extensión creada en los resultados.

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

y usando como

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

    return objects.count > 0 ? objects : nil
}

44
for var i = 0; i < count; i++ debe ser reemplazado confor i in 0 ..< count
Sal

1
Lo anterior es una forma muy confusa de escribir la extensión: extensión Resultados {var array: [Elemento] {return self.map {$ 0}}}
Giles

10

Con Swift 4.2 es tan simple como una extensión:

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

Toda la información genérica necesaria ya es parte de la Resultscual ampliamos.


8

Esta es otra forma de convertir Resultsen Array con una extensión con Swift 3 en una sola línea.

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

Para Swift 4 y Xcode 9.2

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

Con Xcode 10 flatMap está en desuso, puede usarlo compactMappara el mapeo.

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

Como estoy usando este código en la versión 9.2 de XCode, me muestra Uso del tipo no declarado 'T'
Bhavesh Dhaduk

Actualicé mi respuesta, puedes verificarlo.
abdullahselek

Para Xcode 10 y superior, puede usar compactMap en lugar de flatMap para evitar la advertencia.
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: uso de genéricos

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

no es una buena idea convertir Results a Array, porque Results es vago. Pero si necesitas probar esto:

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

pero la mejor manera es pasar resultados donde lo necesite. También puede convertir Resultados a Lista en lugar de Array.

List(realm.objects(class))

Si el primer func no funciona, puede probar este:

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

Después de actualizar RealmSwift a 3.4.0, List no toma argumentos. ¿Cómo convertir una matriz a List en este caso? ¿Alguna idea?
Nishu_Priya

1
@NishuPriya aquí está permitido myList = List <Person> () myList.append (objectsIn: realm.objects (Person.self))
Nosov Pavel

2

No estoy seguro, si hay alguna manera eficiente de hacer esto.

Pero puede hacerlo creando una matriz Swift y anexándola en el bucle.

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

Si sientes que es demasiado lento. Te recomiendo que pases el Resultsobjeto Realm directamente.


Hice algo así solo creando una extensión en Resules. He publicado el código como respuesta. Gracias :)
Sahil Kapoor

Si. Yo también haría eso.
nRewik

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

Entonces, puedes usar como:

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

2

Solución para Swift 4, Reino 3

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

Ahora la conversión se puede hacer de la siguiente manera

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

2
extension Results {
    func materialize() -> [Element] {
        return Array(self)
    }
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.