RealmSwift:将结果转换为Swift数组


143

我要实现的是:

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

    return objects.count > 0 ? objects : nil
}

我怎样才能返回对象[SomeObject],而是如果Results

Answers:


379

很奇怪,答案很简单。这是我的方法:

let array = Array(results) // la fin

它不返回NSArray吗?
sumsumsign

2
@thesummersign Realm最近发生了很大变化,但是可以肯定的是:上面的代码返回了一个Array由结果迭代器构造的Swift 。
Mazyod

4
它返回实体的nil vars(初始值)
Nik Kov

2
我同意@NikKov,它似乎正在返回该实体的nil vars;(
Jon

2
@Jon您如何看待他们为零?似乎因为它们很懒,所以当您查看它们在调试点停止时,它们似乎为空,但如果将它们打印出来,它将访问它们并显示正确的值(对我而言)。
耶利米'18

31

如果您绝对必须将转换ResultsArray,请记住,这Results是懒惰的,因此会有性能和内存开销。但是您可以像results.map { $0 }在swift 2.0(或map(results) { $0 }1.2)中那样一行完成。


哪个版本的Realm?
Sahil Kapoor

31
如果您不想将对Realm的依赖泄漏到项目中太多的类中,这不是必需的吗?
Marcin Kuptel 2015年

15
map { $0 }LazyMapRandomAccessCollection在Swift 3中返回,因此@Mazyod的答案更好。
Legoless

@MarcinKuptel是的,这正是我发现的问题。通过创建符合协议的结构,我已经能够抽象出领域模型,而这正是我在代码库的签名中定义的协议抽象。但是有时我需要转换为数组,有没有办法我可以对我的抽象协议进行惰性收集,使其仅在访问时转换为struct?
帕万

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:[Element] {return self.map {$ 0}}}
Giles

10

使用Swift 4.2,就像扩展一样简单:

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

所有必需的泛型信息已经是Results我们扩展的一部分。


8

这是在单行中Results使用Swift 3扩展名转换为Array 的另一种方法。

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 '18

对于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

将结果转换为数组不是一个好主意,因为结果是惰性的。但是,如果您需要尝试此操作:

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

但更好的方法是在任何需要的地方传递结果。您也可以将结果转换为列表而不是数组。

List(realm.objects(class))

如果第一个功能不起作用,则可以尝试以下操作:

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

将RealmSwift更新为3.4.0之后,List将不接受参数。在这种情况下,如何将数组转换为List?任何想法?
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 2015年

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)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.