RealmSwift: Konvertieren Sie Ergebnisse in Swift Array


143

Was ich implementieren möchte:

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

    return objects.count > 0 ? objects : nil
}

Wie kann ich ein Objekt zurückgeben, als [SomeObject]ob Results?

Antworten:


379

Seltsam, die Antwort ist sehr einfach. So mache ich das:

let array = Array(results) // la fin

Gibt es kein NSArray zurück?
Thesummersign

2
@thesummersign Realm hat sich in letzter Zeit stark verändert, aber eines ist sicher: Der obige Code gibt einen Swift zurück, Arrayder mit dem Ergebnisiterator erstellt wurde.
Mazyod

4
Es gibt keine Variablen der Entität zurück (initial)
Nik Kov

2
Ich stimme @NikKov zu, es scheint, dass keine Variablen der Entität zurückgegeben werden (
Jon

2
@ Jon Wie siehst du, dass sie gleich Null sind? Es scheint, als wären sie faul, wenn Sie sie an einem Debug-Punkt angehalten betrachten, erscheinen sie leer, aber wenn Sie sie ausdrucken, greift sie auf sie zu und zeigt den richtigen Wert (für mich) an.
Jeremiah

31

Wenn Sie unbedingt Ihre konvertieren ResultszuArray denken , dass es einen Leistungs- und Speicheraufwand gibt, da dieser Resultsfaul ist. Sie können dies jedoch in einer Zeile tun, wie results.map { $0 }in Swift 2.0 (oder map(results) { $0 }in 1.2).


Welche Version von Realm?
Sahil Kapoor

31
Ist diese Konvertierung nicht eine Notwendigkeit, wenn Sie die Abhängigkeit von Realm nicht auf zu viele Klassen in Ihrem Projekt übertragen möchten?
Marcin Kuptel

15
map { $0 }wird LazyMapRandomAccessCollectionin Swift 3 zurückkehren, daher ist die @ Mazyod-Antwort besser.
Legoless

@MarcinKuptel ja das ist genau das problem das ich gefunden habe. Ich konnte das Realm-Modell abstrahieren, indem ich eine Struktur erstellte, die einem Protokoll entspricht. Diese Protokollabstraktion definiere ich in meinen Signaturen in meiner Codebasis. Manchmal muss ich jedoch in ein Array konvertieren. Gibt es eine Möglichkeit, eine verzögerte Sammlung meines abstrahierten Protokolls zu erstellen, sodass es nur zur Zugriffszeit in die Struktur konvertiert wird?
Pavan

20

Ich habe eine Lösung gefunden. Erweiterung für Ergebnisse erstellt.

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

und mit like

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++ sollte ersetzt werden durchfor i in 0 ..< count
Sal

1
Das obige ist eine sehr verwirrende Art, die Erweiterung zu schreiben: Erweiterung Ergebnisse {var array: [Element] {return self.map {$ 0}}}
Giles

10

Mit Swift 4.2 ist es so einfach wie eine Erweiterung:

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

Alle benötigten Generika-Informationen sind bereits ein Teil, Resultsden wir erweitern.


8

Dies ist eine weitere Möglichkeit, Resultsin Array mit einer Erweiterung mit Swift 3 in einer einzelnen Zeile zu konvertieren .

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

Für Swift 4 und Xcode 9.2

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

Mit Xcode 10 flatMap veraltet ist , können Sie verwenden compactMapfür die Zuordnung.

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

Da ich diesen Code in der 9.2-Version von XCode verwende, zeigt er mir die Verwendung des nicht deklarierten Typs 'T'
Bhavesh Dhaduk

Meine Antwort wurde aktualisiert. Sie können sie überprüfen.
Abdullahselek

Für Xcode 10 und höher können Sie compactMap anstelle von flatMap verwenden, um die Warnung zu vermeiden.
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
    }
}

Verwendung

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
}

Alternative: Generika verwenden

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

Es ist keine gute Idee, Ergebnisse in Array zu konvertieren, da Ergebnisse faul sind. Aber wenn Sie es brauchen, versuchen Sie Folgendes:

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

Besser ist es jedoch, die Ergebnisse überall dort weiterzugeben, wo Sie sie benötigen. Sie können Ergebnisse auch in Liste anstelle von Array konvertieren.

List(realm.objects(class))

Wenn die erste Funktion nicht funktioniert, können Sie diese ausprobieren:

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

Nach dem Update von RealmSwift auf 3.4.0 akzeptiert List keine Argumente. Wie konvertiere ich in diesem Fall ein Array in List? Irgendeine Idee?
Nishu_Priya

1
@NishuPriya hier sind Sie myList = List <Person> () myList.append (ObjekteIn: Realm.Objects (Person.self))
Nosov Pavel

2

Ich bin mir nicht sicher, ob es dafür einen effizienten Weg gibt.

Sie können dies jedoch tun, indem Sie ein Swift-Array erstellen und es in die Schleife einfügen.

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

Wenn Sie das Gefühl haben, dass es zu langsam ist. Ich empfehle Ihnen, das Realm- ResultsObjekt direkt weiterzugeben .


Ich habe so etwas nur gemacht, indem ich stattdessen eine Erweiterung für Resules erstellt habe. Ich habe den Code als Antwort gepostet. Danke :)
Sahil Kapoor

Ja. Das würde ich auch tun.
nRewik

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

Sie können also Folgendes verwenden:

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

2

Lösung für Swift 4, Realm 3

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

Jetzt kann die Konvertierung wie folgt durchgeführt werden

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

2
extension Results {
    func materialize() -> [Element] {
        return Array(self)
    }
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.