Brittany
Brittany

Reputation: 1439

iOS - Shuffle/Randomize order of objects in NSMutableArray

I want to shuffle/randomize the order of the items inside my NSMutableArray when method reloadData is executed. I tried the below, but console keeps throwing me the following error:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI exchangeObjectAtIndex:withObjectAtIndex:]: unrecognized selector sent to instance 0x1748b2c60'

Any idea why this might be? I'm stumped.

ViewController.h

@property (strong, retain) NSMutableArray *neighbourData;

ViewController.m

- (void)reloadData:(id)sender
{


     NSMutableDictionary *viewParams = [NSMutableDictionary new];
            [viewParams setValue:@"u000" forKey:@"view_name"];
            [DIOSView viewGet:viewParams success:^(AFHTTPRequestOperation *operation, id responseObject) {



                self.neighbourData = (NSMutableArray *)responseObject;

                [self.tableView reloadData];

                NSUInteger count = [self.neighbourData count];
                for (NSUInteger i = 0; i < count; ++i) {
                    // Select a random element between i and end of array to swap with.
                    int nElements = count - i;
                    int n = (arc4random() % nElements) + i;
                    [self.neighbourData exchangeObjectAtIndex:i withObjectAtIndex:n];
                }


                NSLog(@"This is the neighbourdata %@",self.neighbourData);


            } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                NSLog(@"Failure: %@", [error localizedDescription]);
            }];

Upvotes: 0

Views: 193

Answers (3)

Jidong Chen
Jidong Chen

Reputation: 450

self.neighbourData = (NSMutableArray *)responseObject; You have to make sure that your responseObject is an instance of NSMutableArray here. Even though you cast the type responseObject to NSMutableArray, it will crash if it's not an instance of NSMutableArray because it dose not have a exchangeObjectAtIndex:withObjectAtIndex:. In this case your responseObject is a NSArray instance, your could change the code to: NSArray *tmp = (NSArray *)responseObject; self.neighbourData = [tmp mutableCopy]; I think this works for you.

Upvotes: 0

Josh Homann
Josh Homann

Reputation: 16327

For production you really ought to use the built in Fisher-Yates shuffle in Gamekit. If you are doing this for leaning purposes then the problem is in the line:

int n = (arc4random() % nElements) + i;

You are making a random number from the first to the last element and then you are adding i to it. Clearly this means that your index can now be out of bounds. Get rid of the + i.

Upvotes: 0

rmaddy
rmaddy

Reputation: 318794

The error indicates that responseObject is actually a non-mutable NSArray. The cast you applied simply lies to the compiler but it doesn't actually change anything at runtime.

Change:

self.neighbourData = (NSMutableArray *)responseObject;

to:

self.neighbourData = [(NSArray *)responseObject mutableCopy];

Upvotes: 2

Related Questions