What you are looking for is called a shuffle
(think shuffling a deck of cards - same data, different order). The following method can be used to swap two objects within a mutable array.
- (void)exchangeObjectAtIndex:(NSUInteger)idx1
withObjectAtIndex:(NSUInteger)idx2
You cannot enumerate over an array while you are modifying it, and I would refrain from looping over the elements of the array as well. Instead, create a for-loop with an index and use arc4random to generate the second swap index.
for (NSUInteger n = 0; n < array.count; n++) {
NSUInteger m = arc4random_uniform(array.count);
[array exchangeObjectAtIndex:n withObjectAtIndex:m];
}
There's more sophistication that can be added like checking to see if n == m
or negating some kind of bias but this should get you a "mostly" random sampling of the original array.
[Swift]
Swift exchange Method swaps two items in a mutable array.
func exchangeObjectAtIndex(_ idx1: Int,
withObjectAtIndex idx2: Int)
User Nate Cook provides several good shuffling methods for Swift
here. I'm copying his mutating Array method here, as it is closest to the Objective-C method described above.
extension Array {
mutating func shuffle() {
for i in 0..<(count - 1) {
let j = Int(arc4random_uniform(UInt32(count - i))) + i
exchangeObjectAtIndex(i, withObjectAtIndex: j)
}
}
}
var numbers = [1, 2, 3, 4, 5, 6, 7, 8]
numbers.shuffle()