RealmSwift: Ubah Hasil menjadi Swift Array

143

Apa yang ingin saya terapkan:

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

    return objects.count > 0 ? objects : nil
}

Bagaimana saya bisa mengembalikan objek seolah- [SomeObject]olah jika Results?

Sahil Kapoor
sumber

Jawaban:

379

Aneh, jawabannya sangat lurus ke depan. Inilah cara saya melakukannya:

let array = Array(results) // la fin
Mazyod
sumber
bukankah itu mengembalikan NSArray?
Musim panas
2
@thesummersign Realm telah banyak berubah baru-baru ini, tetapi satu hal yang pasti: Kode di atas mengembalikan Swift yang Arraydibangun dengan hasil iterator.
Mazyod
4
Ini mengembalikan nol entitas (awal)
Nik Kov
2
Saya setuju dengan @NikKov, tampaknya akan mengembalikan nol entitas; (
Jon
2
@ Jon Bagaimana Anda melihat bahwa mereka nihil? Sepertinya karena mereka malas, ketika Anda melihat mereka berhenti pada titik debug mereka tampak kosong tetapi jika Anda mencetaknya itu mengaksesnya dan menunjukkan nilai yang benar (untuk saya).
Yeremia
31

Jika Anda benar-benar harus mengonversi Resultske Array, ingat ada kinerja dan memori overhead, karena Resultsmalas. Tetapi Anda bisa melakukannya dalam satu baris, seperti results.map { $0 }pada swift 2.0 (atau map(results) { $0 }1.2).

segiddin
sumber
Versi Realm yang mana?
Sahil Kapoor
31
Bukankah konversi ini suatu keharusan jika Anda tidak ingin membocorkan ketergantungan pada Realm ke terlalu banyak kelas dalam proyek Anda?
Marcin Kuptel
15
map { $0 }akan kembali LazyMapRandomAccessCollectiondalam Swift 3, jadi jawaban @Mazyod lebih baik.
Legoless
@ Marscinupuptel ya itulah masalah yang saya temukan. Saya sudah bisa mengabstraksi model ranah dengan membuat struct yang sesuai dengan protokol, dan abstraksi protokol inilah yang saya definisikan dalam tanda tangan saya di basis kode saya. Namun kadang-kadang saya perlu mengkonversi ke array, apakah ada cara saya dapat memiliki koleksi malas protokol abstrak saya sehingga hanya mengkonversi ke struct pada waktu akses?
Pavan
20

Saya menemukan solusinya. Ekstensi dibuat pada Hasil.

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

dan menggunakan like

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

    return objects.count > 0 ? objects : nil
}
Sahil Kapoor
sumber
4
for var i = 0; i < count; i++ harus diganti denganfor i in 0 ..< count
Sal
1
Cara di atas sangat membingungkan dalam menulis ekstensi: ekstensi Hasil {var array: [Elemen] {return self.map {$ 0}}}
Giles
10

Dengan Swift 4.2, sesederhana ekstensi:

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

Semua informasi generik yang diperlukan sudah menjadi bagian dari Resultsyang kami sampaikan.

NeverwinterMoon
sumber
8

Ini cara lain untuk mengkonversi Resultsmenjadi Array dengan ekstensi dengan Swift 3 dalam satu baris.

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

Untuk Swift 4 dan Xcode 9.2

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

Dengan Xcode 10 flatMap sudah usang Anda dapat menggunakan compactMapuntuk pemetaan.

extension Results {
    func toArray<T>(type: T.Type) -> [T] {
        return compactMap { $0 as? T }
    }
}
abdullahselek
sumber
Saat saya menggunakan kode ini dalam versi 9.2 dari XCode, kode ini menunjukkan saya Penggunaan tipe 'T' yang tidak dideklarasikan
Bhavesh Dhaduk
Diperbarui jawaban saya, Anda dapat memeriksanya.
abdullahselek
Untuk Xcode 10 ke atas, Anda dapat menggunakan compactMap alih-alih flatMap untuk menghindari peringatan.
Metodij Zdravkin
6

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

Pemakaian

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
}

Alternatif: Menggunakan obat generik

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
}
Jaseem Abbas
sumber
4

itu bukan ide yang baik untuk mengonversi Hasil ke Array, karena Hasil malas. Tetapi jika Anda perlu mencoba ini:

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

tetapi cara yang lebih baik adalah memberikan Hasil di mana pun Anda butuhkan. Anda juga dapat mengonversi Hasil ke Daftar alih-alih Array.

List(realm.objects(class))

jika fungsi pertama tidak berfungsi, Anda dapat mencoba yang ini:

var refrenceBook:[RefrenceProtocol] = []
let faceTypes = Array(realm.objects(FaceType))
refrenceBook = faceTypes.map({$0 as FaceType})
Nosov Pavel
sumber
Setelah memperbarui RealmSwift ke 3.4.0, Daftar tidak mengambil argumen. Bagaimana cara mengubah array ke Daftar dalam kasus ini? Ada ide?
Nishu_Priya
1
@NishuPriya di sini Anda membiarkan myList = Daftar <Person> () myList.append (objekIn: realm.objects (Person.self))
Nosov Pavel
2

Saya tidak yakin, apakah ada cara efisien untuk melakukan ini.

Tetapi Anda bisa melakukannya dengan membuat array Swift dan menambahkannya dalam 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
}

Jika Anda merasa itu terlalu lambat. Saya sarankan Anda untuk membagikan Resultsobjek Realm secara langsung.

nRewik
sumber
Saya melakukan sesuatu seperti itu hanya dengan membuat ekstensi di Resules sebagai gantinya. Saya telah memposting kode sebagai jawaban. Terima kasih :)
Sahil Kapoor
ya. Saya akan melakukannya juga.
nRewik
2
extension Results {
    var array: [Element]? {
        return self.count > 0 ? self.map { $0 } : nil
    }
}

Jadi, Anda bisa menggunakan like:

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

Solusi untuk Swift 4, Realm 3

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

Sekarang konversi dapat dilakukan seperti di bawah ini

let array = Realm().objects(SomeClass).toArray(ofType: SomeClass.self)
Vinayak
sumber
2
extension Results {
    func materialize() -> [Element] {
        return Array(self)
    }
}
Desmond Hume
sumber