Search code examples
iosswiftrealm

How can i shuffle RLMResults in swift?


Any idea how can i shuffle randomly for RLMResults? I couldn't find anyway to do it via RLMSortDescriptor.

I tried writing my own swap algorithm, but it's giving me error (cannot assign to results of this expression*).

func simpleRandomSwap(rlmobjects:RLMResults!) -> RLMResults! {
    if (rlmobjects != nil && rlmobjects.count > 0) {

        let indexcount = Int(rlmobjects.count)

        for (var i=0 ; i<indexcount; i++) {
            let randomUInt:UInt = UInt(arc4random_uniform(UInt32(indexcount)))
            let myuint = UInt(i)


            // simple swap
            var temp = rlmobjects.objectAtIndex(myuint)
            rlmobjects.objectAtIndex(randomUInt) = rlmobjects.objectAtIndex(myuint)
            rlmobjects.objectAtIndex(myuint) = temp


        } // end for loop

    }


    return rlmobjects
}

Solution

  • First a quick note: RLMResults have no defined order unless they are sorted via RLMSortDescriptor.

    Instead, to randomly sort you have two options:

    1. Add a integer property to your object schema and assign random values to all the objects. You can then use a RLMSortDescriptor with RLMResults to sort the objects.

    2. As mentioned in the comments above, copy the RLMObjects into an array and perform a random sort on this.

    Here is an extension to RLMObject that does this:

    extension RLMResults {
        public func toShuffledArray<T>(ofType: T.Type) -> [T] {
    
            var array = [T]()
    
            for result in self {
                if let result = result as? T {
                    array.append(result)
                }
            }
    
            let count = array.count
    
            if count > 1 {
                for i in 0..<(count - 1) {
                    let j = Int(arc4random_uniform(UInt32(count - i))) + Int(i)
                    swap(&array[i], &array[j])
                }
            }
    
            return array
        }
    }
    

    You would call it like this:

    let shuffled = results.toShuffledArray(TestObject.self)