Ad

Our DNA is written in Swift
Jump

Shuffling an NSArray

For a project I am working on I needed to shuffle the contents of an NSArray without harming the items themselves. NSArray is a convenient container because it does not care about what you put inside. This is because you don’t (put objects into arrays), you only pretend.

You cannot add an object itself into an array but instead you always insert pointers to class instances. NSArray and its bigger cousin NSMutableArray will keep track of the pointers and memory management of the items so you don’t have to. This is a custom category for NSArray that is useful for shuffling the contents, regardless of their class type.

The header NSArray+Helpers.h:

#import
 
@interface NSArray (Helpers)
 
- (NSArray *) shuffled;
 
@end

The implementation NSArray+Helpers.m:

#import "NSArray+Helpers.h"
 
@implementation NSArray (Helpers)
 
- (NSArray *) shuffled
{
	// create temporary autoreleased mutable array
	NSMutableArray *tmpArray = [NSMutableArray arrayWithCapacity:[self count]];
 
	for (id anObject in self)
	{
		NSUInteger randomPos = arc4random()%([tmpArray count]+1);
		[tmpArray insertObject:anObject atIndex:randomPos];
	}
 
	return [NSArray arrayWithArray:tmpArray];  // non-mutable autoreleased copy
}
 
@end

The implemented method works by adding the object references to a temporary NSMutableArray at random positions. The arithmetic is necessary that only valid positions are chosen at random. If you try to insert an object with too high an index then your app crashes with an exception.

How to use it:

#import "NSArray+Helpers.h"
 
// test shuffling
NSArray *arr = [[NSArray arrayWithObjects:@"1",@"2", @"3", @"4", nil] shuffled];
NSLog([arr description]);

You might have noticed previously that I have grown very fond of Class Categories. This is the method of choice if you want to teach existing classes new tricks.


Categories: Recipes

17 Comments »

  1. Is NSMutableArray *tmpArray auto-released because you passed the pointer to arrayWithArray?

  2. No, because I marked it as autoreleased! ๐Ÿ˜‰ (After you caught me on this one)

  3. I know i’m just nit-picking now, but [NSMutableArray arrayWithCapacity:[self count]] would be a bit more readable. ๐Ÿ˜‰

  4. Ok, you win. Would you consider writing a guest column for this blog?

  5. I would love to do a guest post on marketing an iPhone app.