RealmSwift: แปลงผลลัพธ์เป็น Swift Array


143

สิ่งที่ฉันต้องการนำไปใช้:

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

    return objects.count > 0 ? objects : nil
}

ฉันจะกลับมาเป็นวัตถุ[SomeObject]แทนถ้าResults?

คำตอบ:


379

แปลกคำตอบนั้นตรงไปตรงมามาก นี่คือวิธีที่ฉันทำ:

let array = Array(results) // la fin

ไม่ส่งคืน NSArray หรือ
thesummersign

2
@thesummersign Realm ได้เปลี่ยนแปลงไปมากเมื่อเร็ว ๆ นี้ แต่สิ่งหนึ่งที่แน่นอนคือ: โค้ดด้านบนจะส่งคืน Swift ที่Arrayสร้างขึ้นพร้อมกับ iterator ผลลัพธ์
Mazyod

4
มันจะคืนค่าศูนย์ของเอนทิตี (เริ่มต้น)
Nik Kov

2
ฉันเห็นด้วยกับ @NikKov ดูเหมือนว่าจะคืนค่าศูนย์ของเอนทิตี้ (
Jon

2
@ จอนคุณเห็นได้อย่างไรว่าพวกเขาเป็นศูนย์? ดูเหมือนว่าพวกเขาจะขี้เกียจเมื่อคุณดูพวกเขาหยุดที่จุดแก้ปัญหาพวกเขาจะว่างเปล่า แต่ถ้าคุณพิมพ์พวกเขามันเข้าถึงพวกเขาและแสดงค่าที่ถูกต้อง (สำหรับฉัน)
ยิระ

31

ถ้าคุณอย่างต้องแปลงของคุณResultsจะArrayเก็บไว้ในใจมีประสิทธิภาพการทำงานและค่าหน่วยความจำตั้งแต่Resultsเป็นคนขี้เกียจ แต่คุณสามารถทำได้ในหนึ่งบรรทัดเช่นเดียวกับresults.map { $0 }ใน swift 2.0 (หรือmap(results) { $0 }ใน 1.2)


Realm เวอร์ชันใด
Sahil Kapoor

31
การแปลงนี้ไม่จำเป็นหรือไม่ถ้าคุณไม่ต้องการรั่วไหลจากการพึ่งพา Realm ไปยังคลาสที่มากเกินไปในโครงการของคุณ?
Marcin Kuptel

15
map { $0 }จะกลับมาเป็นLazyMapRandomAccessCollectionSwift 3 ดังนั้นคำตอบ @ Myazy จะดีกว่า
Legoless

@MarcinKuptel ใช่ว่าเป็นปัญหาที่ฉันพบ ฉันสามารถแยกโมเดล realm ออกได้ด้วยการสร้าง struct ที่สอดคล้องกับโปรโตคอลและนี่เป็นนามธรรมของโปรโตคอลที่ฉันกำหนดไว้ในลายเซ็นของฉันใน codebase ของฉัน อย่างไรก็ตามบางครั้งฉันจำเป็นต้องแปลงเป็นอาเรย์มีวิธีที่ฉันสามารถมีคอลเลกชันที่ขี้เกียจของโปรโตคอลนามธรรมของฉันเพื่อที่จะแปลงเป็นโครงสร้างที่เวลาเข้าถึงเท่านั้น?
Pavan

20

ฉันพบวิธีแก้ปัญหา สร้างส่วนขยายบนผลลัพธ์

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

และการใช้งานเช่น

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++ ควรแทนที่ด้วยfor i in 0 ..< count
Sal

1
ข้างต้นเป็นวิธีที่สับสนมากในการเขียนส่วนขยาย: ส่วนขยายผลลัพธ์ {var array: [องค์ประกอบ] {return self.map {$ 0}}}
ไจล์ส

10

ด้วย Swift 4.2 มันง่ายเหมือนส่วนขยาย:

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

ข้อมูลทั่วไปที่จำเป็นทั้งหมดเป็นส่วนหนึ่งของResultsเรา


8

นี่เป็นอีกวิธีหนึ่งในการแปลงResultsเป็น Array ด้วยส่วนขยายด้วยSwift 3ในบรรทัดเดียว

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

สำหรับSwift 4และ Xcode 9.2

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

ด้วยXcode 10 flatMapเลิกใช้แล้วคุณสามารถใช้compactMapสำหรับการจับคู่

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

ในขณะที่ฉันใช้รหัสนี้ในรุ่น XCode 9.2 ก็แสดงให้ฉันเห็นการใช้งานประเภท 'T' ที่ไม่ได้ประกาศ
Bhavesh Dhaduk

อัปเดตคำตอบของฉันคุณสามารถตรวจสอบได้
abdullahselek

สำหรับ Xcode 10 ขึ้นไปคุณสามารถใช้ compactMap แทน flatMap เพื่อหลีกเลี่ยงคำเตือน
Metodij Zdravkin

6

สวิฟท์ 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
    }
}

การใช้

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
}

ทางเลือก: การใช้ยาชื่อสามัญ

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

ไม่ใช่ความคิดที่ดีที่จะแปลง Results เป็น Array เพราะ Results เป็นสันหลังยาว แต่ถ้าคุณต้องการลอง:

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

แต่วิธีที่ดีกว่าคือการส่งผลลัพธ์ทุกที่ที่คุณต้องการ นอกจากนี้คุณสามารถแปลงผลลัพธ์เป็นรายการแทนที่จะเป็นอาเรย์

List(realm.objects(class))

ถ้า func แรกไม่ทำงานคุณสามารถลองอันนี้:

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

หลังจากอัปเดต RealmSwift เป็น 3.4.0 รายการจะไม่รับข้อโต้แย้ง วิธีการแปลงอาร์เรย์เป็นรายการในกรณีนี้ ความคิดใด ๆ
Nishu_Priya

1
@NishuPriya ที่นี่คุณจะปล่อยให้ myList = List <Person> () myList.append (objectsIn: realm.objects (Person.self))
Nosov Pavel

2

ฉันไม่แน่ใจว่าหากมีวิธีใดที่มีประสิทธิภาพในการทำเช่นนี้

แต่คุณสามารถทำได้โดยสร้างอาร์เรย์ Swift และผนวกเข้าไปในลูป

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

ถ้าคุณรู้สึกว่ามันช้าเกินไป ฉันแนะนำให้คุณส่งต่อResultsวัตถุRealm โดยตรง


ฉันทำบางสิ่งเช่นนั้นโดยการสร้างส่วนขยายของ Resules แทน ฉันโพสต์รหัสเป็นคำตอบ ขอบคุณ :)
Sahil Kapoor

ใช่. ฉันก็จะทำเช่นนั้น
nRewik

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

ดังนั้นคุณสามารถใช้เช่น:

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

2

โซลูชันสำหรับSwift 4, Realm 3

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

ตอนนี้การแปลงสามารถทำได้ดังนี้

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.