RealmSwift: Chuyển đổi kết quả sang Swift Array


143

Những gì tôi muốn thực hiện:

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

    return objects.count > 0 ? objects : nil
}

Làm thế nào tôi có thể trả lại đối tượng [SomeObject]thay vì nếu Results?

Câu trả lời:


379

Thật kỳ lạ, câu trả lời là rất thẳng về phía trước. Đây là cách tôi làm điều đó:

let array = Array(results) // la fin

nó không trả về NSArray sao?
thesummersign

2
@thesummersign Realm đã thay đổi rất nhiều gần đây, nhưng có một điều chắc chắn: Đoạn mã trên trả về một Swift được Arrayxây dựng với trình lặp kết quả.
Mazyod

4
Nó trả về số không của thực thể (ban đầu)
Nik Kov

2
Tôi đồng ý với @NikKov, có vẻ như họ sẽ trả lại số tiền của thực thể; (
Jon

2
@Jon Làm thế nào bạn thấy rằng họ là con số không? Có vẻ như vì họ lười biếng, khi bạn nhìn vào họ dừng lại ở điểm gỡ lỗi, họ có vẻ trống rỗng nhưng nếu bạn in chúng ra, nó sẽ truy cập vào chúng và hiển thị giá trị chính xác (đối với tôi).
Giê-rê-mi

31

Nếu bạn hoàn toàn phải chuyển đổi Resultsthành Array, hãy nhớ rằng có hiệu năng và chi phí bộ nhớ, vì Resultslười biếng. Nhưng bạn có thể làm điều đó trong một dòng, như results.map { $0 }trong swift 2.0 (hoặc map(results) { $0 }trong 1.2).


Phiên bản nào của Vương quốc?
Sahil Kapoor

31
Đây có phải là chuyển đổi không cần thiết nếu bạn không muốn rò rỉ sự phụ thuộc vào Realm vào quá nhiều lớp trong dự án của bạn?
Marcin Kuptel

15
map { $0 }sẽ trở lại LazyMapRandomAccessCollectiontrong Swift 3, vì vậy câu trả lời @Mazyod là tốt hơn.
Legoless

@MarcinKuptel vâng, đó chính xác là vấn đề tôi tìm thấy. Tôi đã có thể trừu tượng hóa mô hình cõi bằng cách tạo ra một cấu trúc phù hợp với một giao thức, và đó là sự trừu tượng hóa giao thức mà tôi xác định trong các chữ ký của mình trong cơ sở mã của mình. Tuy nhiên, đôi khi tôi cần chuyển đổi thành một mảng, có cách nào để tôi có thể có một bộ sưu tập lười biếng của giao thức trừu tượng hóa để nó chỉ chuyển đổi sang cấu trúc khi truy cập không?
Pavan

20

Tôi tìm thấy một giải pháp. Tạo phần mở rộng trên Kết quả.

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

và sử dụng như

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++ nên được thay thế bằngfor i in 0 ..< count
Sal

1
Cách trên rất khó hiểu khi viết phần mở rộng: phần mở rộng Kết quả {var mảng: [Element] {return self.map {$ 0}}}
Giles

10

Với Swift 4.2, nó đơn giản như một phần mở rộng:

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

Tất cả các thông tin chung chung cần thiết đã là một phần trong Resultsđó chúng tôi mở rộng.


8

Đây là một cách khác để chuyển đổi Resultsthành Array với phần mở rộng với Swift 3 trong một dòng duy nhất.

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

Dành cho Swift 4 và Xcode 9.2

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

Với Xcode 10 flatMap không dùng nữa, bạn có thể sử dụng compactMapđể ánh xạ.

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

Khi tôi đang sử dụng mã này trong phiên bản 9.2 của XCode, nó hiển thị cho tôi Sử dụng loại không được khai báo 'T'
Bhavesh Dhaduk

Cập nhật câu trả lời của tôi, bạn có thể kiểm tra nó.
abdullahselek

Đối với Xcode 10 trở lên, bạn có thể sử dụng compactMap thay vì FlatMap để tránh cảnh báo.
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
    }
}

Sử dụng

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
}

Thay thế: Sử dụng thuốc generic

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

Không nên chuyển đổi Kết quả thành Mảng, vì Kết quả là lười biếng. Nhưng nếu bạn cần thử điều này:

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

nhưng cách tốt hơn là vượt qua Kết quả bất cứ nơi nào bạn cần. Ngoài ra, bạn có thể chuyển đổi Kết quả thành Danh sách thay vì Mảng.

List(realm.objects(class))

nếu func đầu tiên không hoạt động, bạn có thể thử cái này:

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

Sau khi cập nhật RealmSwift lên 3.4.0, Danh sách không nhận đối số. Làm thế nào để chuyển đổi một mảng thành Danh sách trong trường hợp này? Bất kỳ ý tưởng?
Nishu_Priya

1
@NishuPriya ở đây bạn hãy để myList = List <Person> () myList.append (objectIn: realm.objects (Person.elf))
Nosov Pavel

2

Tôi không chắc chắn, nếu có bất kỳ cách hiệu quả để làm điều này.

Nhưng bạn có thể làm điều đó bằng cách tạo một mảng Swift và nối nó vào vòng lặp.

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

Nếu bạn cảm thấy nó quá chậm. Tôi khuyên bạn nên vượt qua xung quanh Resultsđối tượng Realm trực tiếp.


Tôi đã làm một cái gì đó như thế chỉ bằng cách tạo một phần mở rộng trên Resules thay thế. Tôi đã đăng mã như câu trả lời. Cảm ơn :)
Sahil Kapoor

vâng Tôi cũng sẽ làm điều đó.
nRewik

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

Vì vậy, bạn có thể sử dụng như:

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

2

Giải pháp cho Swift 4, Realm 3

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

Bây giờ chuyển đổi có thể được thực hiện như dưới đây

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

2
extension Results {
    func materialize() -> [Element] {
        return Array(self)
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.