I've started with the idea of extending NSArray class with method returning an array with shuffled elements, which can be achieved using Objective-C categories [1], in following way:
Define the Shuffling category (NSArray+Shuffling.h):
#import <Foundation/Foundation.h>
@interface NSArray (Shuffling)
- (NSArray *) shuffle;
@end
Implement the category using modern version of Fisher-Yates shuffle algorithm [2] (NSArray+Shuffling.m):#import "NSArray+Shuffling.h"
@implementation NSArray (Shuffling)
- (NSArray *) shuffle
{
NSMutableArray *result = [self mutableCopy];
int j = 0;
for (int i = [result count]; i >= 1; i--) {
j = arc4random() % i;
[result exchangeObjectAtIndex:j withObjectAtIndex:i-1];
}
return [[result copy] autorelease];
}
@end
We have the code, let's put it into some project where we could test it - static library will be enough for our needs, let's use it:
XCode 4 let you select if you will use Unit Tests for the project when you define its name:
After creating new project, we will add our source code to it:
It will be new Objective-C Category:
based on NSArray:
and bound to the primary project target:
Now we can put the source code described at the beginning of this post into newly created files.
Project created the above way with XCode 4 has automatically generated Unit Test, which can be run at this point to check if everything works correctly - before you do it, check if you selected the iPhone Simulator for running it - it cannot be done on physical device.
Let's run the XCode 4 generated Unit Test:
What we will see at this point will be:
It looks like everything is fine till now :) - let's create our own test instead of STFail macro:
- (void)testExample
{
NSArray *array = [NSArray arrayWithObjects: [NSNumber numberWithInt:1], [NSNumber numberWithInt:2], [NSNumber numberWithInt:3], [NSNumber numberWithInt:4], [NSNumber numberWithInt:5], [NSNumber numberWithInt:6], [NSNumber numberWithInt:7], [NSNumber numberWithInt:8], nil];
NSArray *shuffledArray = [array shuffle];
STAssertNotNil(shuffledArray, @"Shuffled array is nil");
STAssertTrue([shuffledArray retainCount] == 1, @"Retain count: %i", [shuffledArray retainCount]);
NSLog(@"Shuffled: %@", shuffledArray);
}
When you run it this time you'll get the exception:
because our static library was not used by the linker, and thus our NSArray extension is not visible, let's correct it by adding appropriate linker flag [3] (-all_load):
When you run the test now you should receive something like this:
As you see this time Unit Test is working correctly, and our shuffling code too :)
Few links for the dessert:
No comments:
Post a Comment