RealmSwift: конвертировать результаты в массив Swift


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созданный с помощью итератора результатов.
Mazyod

4
Возвращает ноль переменных сущности (начальная)
Ник Ков

2
Я согласен с @NikKov, похоже, он возвращает ноль переменных сущности; (
Jon

2
@Jon Как ты видишь, что они ноль? Кажется, что поскольку они ленивые, когда вы смотрите на них, остановленные в точке отладки, они кажутся пустыми, но если вы распечатываете их, они получают к ним доступ и показывают правильное значение (для меня).
Иеремия

31

Если вам абсолютно необходимо преобразовать его Resultsв Array, имейте в виду, что это Resultsсвязано с производительностью и объемом памяти, так как это лениво. Но вы можете сделать это в одну строку, как results.map { $0 }в Swift 2.0 (или map(results) { $0 }в 1.2).


Какая версия Realm?
Сахил Капур

31
Не является ли это преобразование необходимостью, если вы не хотите передавать зависимость от Realm слишком многим классам в вашем проекте?
Марцин Куптел

15
map { $0 }вернется LazyMapRandomAccessCollectionв Swift 3, так что ответ @Mazyod лучше.
Legoless

@MarcinKuptel да, это именно та проблема, которую я нашел. Я смог абстрагировать модель области, создав структуру, соответствующую протоколу, и именно эту абстракцию протокола я определяю в своих сигнатурах в своей кодовой базе. Однако иногда мне нужно преобразовать в массив, есть ли способ, которым я могу иметь ленивую коллекцию моего абстрактного протокола, чтобы он преобразовывался только в структуру во время доступа?
Паван

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
Вышеприведённый способ написания расширения очень запутан: расширение Results {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 в одну строку.

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

Поскольку я использую этот код в версии 9.2 XCode, он показывает мне использование необъявленного типа 'T'
Бхавеш Дхадук

Обновил мой ответ, вы можете проверить его.
abdullahselek

Для Xcode 10 и выше вы можете использовать compactMap вместо flatMap, чтобы избежать предупреждения.
Методий Здравкин

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

использование

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 не принимает аргументы. Как преобразовать массив в список в этом случае? Любая идея?
Nishu_Priya

1
@NishuPriya здесь вы можете позволить myList = List <Person> () myList.append (objectsIn: realm.objects (Person.self))
Носов Павел

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. Я отправил код как ответ. Спасибо :)
Сахил Капур

Да. Я бы тоже так сделал.
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)

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.