RealmSwift: Converter resultados em matriz rápida


143

O que eu quero implementar:

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

    return objects.count > 0 ? objects : nil
}

Como posso retornar um objeto como [SomeObject]se Results?

Respostas:


379

Estranho, a resposta é muito direta. Aqui está como eu faço isso:

let array = Array(results) // la fin

não retorna um NSArray?
Thesummersign

2
@thesummersign O domínio está mudando muito recentemente, mas uma coisa é certa: o código acima retorna um Swift Arrayconstruído com o iterador de resultados.
Mazyod 13/11/2015

4
Ele retornar vars nil da entidade (inicial)
Nik Kov

2
Eu concordo com @NikKov, parece estar retornando nulos vars da entidade; (
Jon

2
@ Jon Como você está vendo que eles são nulos? Parece que, como eles são preguiçosos, quando você os vê parados em um ponto de depuração, eles parecem vazios, mas se você os imprime, os acessa e mostra o valor correto (para mim).
Jeremiah

31

Se você absolutamente precisa converter o seu Resultspara Array, lembre-se de que há uma sobrecarga de desempenho e memória, pois Resultsé preguiçoso. Mas você pode fazer isso em uma linha, como results.map { $0 }no swift 2.0 (ou map(results) { $0 }no 1.2).


Qual versão do Reino?
Sahil Kapoor

31
Essa conversão não é necessária se você não deseja vazar a dependência do Realm para muitas classes no seu projeto?
Marcin Kuptel 10/10/2015

15
map { $0 }retornará LazyMapRandomAccessCollectionno Swift 3, então a resposta do @Mazyod é melhor.
Legoless 14/09/16

@ MarcinKuptel sim, esse é exatamente o problema que encontrei. Consegui abstrair o modelo de região criando uma estrutura que se adapta a um protocolo, e é essa abstração de protocolo que eu defino nas minhas assinaturas na minha base de código. No entanto, às vezes eu preciso converter para uma matriz, existe uma maneira de ter uma coleção lenta do meu protocolo abstraído para que ele apenas seja convertido na estrutura no momento do acesso?
Pavan

20

Eu encontrei uma solução. Extensão criada em 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
    }
}

e usando como

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++ deve ser substituído porfor i in 0 ..< count
Sal

1
A descrição acima é uma maneira muito confusa de escrever a extensão: extension Results {array de variedades: [Element] {return self.map {$ 0}}}
Giles

10

Com o Swift 4.2, é tão simples quanto uma extensão:

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

Todas as informações genéricas necessárias já fazem parte das Resultsquais estendemos.


8

Essa é outra maneira de converter Resultsem Array com uma extensão com o Swift 3 em uma única linha.

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

Para Swift 4 e Xcode 9.2

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

Com o Xcode 10 flatMap está obsoleto, você pode usar compactMappara mapear.

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

Como eu estou usando esse código em 9,2 versão do Xcode, ele me mostra Uso de tipo não declarado 'T'
Bhavesh Dhaduk

Atualizado minha resposta, você pode conferir.
abdullahselek

Para o Xcode 10 e superior, você pode usar o compactMap em vez do flatMap para evitar o aviso.
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: Usando 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

não é uma boa ideia converter Resultados em Matriz, porque Resultados é preguiçoso. Mas se você precisar, tente o seguinte:

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

mas a melhor maneira é passar os Resultados sempre que precisar. Além disso, você pode converter Resultados em Lista em vez de Matriz.

List(realm.objects(class))

se a primeira função não estiver funcionando, você pode tentar esta:

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

Depois de atualizar o RealmSwift para 3.4.0, a Lista não aceita argumentos. Como converter uma matriz para List neste caso? Qualquer ideia?
Nishu_Priya

1
@NishuPriya aqui está você deixe myList = List <Person> () minhalista.append (objectsIn: realm.objects (Person.self))
Nosov Pavel

2

Não tenho certeza, se existe alguma maneira eficiente de fazer isso.

Mas você pode fazer isso criando uma matriz Swift e anexando-a no loop.

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 você sentir que é muito lento. Eu recomendo que você passe Resultsdiretamente o objeto Realm .


Fiz algo assim apenas criando uma extensão no Resules. Publiquei o código como resposta. Obrigado :)
Sahil Kapoor

sim. Eu faria isso também.
NRewik

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

Então, você pode usar como:

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

2

Solução para Swift 4, Domínio 3

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

Agora a conversão pode ser feita como abaixo

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

2
extension Results {
    func materialize() -> [Element] {
        return Array(self)
    }
}
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.