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?
підписання

2
@thesummersign Realm останнім часом дуже багато змінюється, але одне - це точно: Код вище повертає Swift, Arrayпобудований з ітератором результатів.
Mazyod

4
Він повертає нульові зміни сутності (початковий)
Нік Ков

2
Я згоден з @NikKov, здається, повертається нуль вари суті; (
Jon

2
@Jon Як ти бачиш, що вони нульові? Здається, так як вони ледачі, коли ви дивитесь на них, що зупиняються в точці налагодження, вони здаються порожніми, але якщо ви роздруковуєте їх, вони отримують доступ до них і показують правильне значення (для мене).
Єремія

31

Якщо ви абсолютно повинні перетворити свій Resultsна Array, майте на увазі, що продуктивність і пам'ять накладні, оскільки Resultsце лінь. Але ви можете зробити це в одному рядку, як results.map { $0 }у швидкому 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
Сказане вище дуже заплутано пише написання розширення: розширення Результати {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"
Bhavesh Dhaduk

Оновлена ​​моя відповідь, ви можете її перевірити.
abdullahselek

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

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 не бере аргументів. Як перетворити масив у Список у цьому випадку? Будь-яка ідея?
Nishu_Priya

1
@NishuPriya тут вам дозволено myList = Список <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.