-3

I've a UIViewController that contains a UITableView and when I call the method "requireObjects", this last populate the arrays to configure the table. I state that the cellForRowAtIndexPath method work properly and dequeue a number of cells based on [_arrID count].

Each populated array has a matching index with all other arrays. For example arrID[5] = 453 corresponds to arrNames[5] = "Jean" and corresponds to arrStyle[5] = "Angry" and corresponds to arrLocation[5] = "New York" and corresponds to arrProfileSnaps[5] = jean.png.

These 5 arrays for example make up the fifth cell in the tableView. The method "requireObjects" succeeds and the table is built correctly. The problem arises when I call this method while it is still running. I wish that the method stops and repeats when I click a button. Or desperate times, it's good also that the method ends its execution and repeat when I click the button. But unfortunately my app crashes. Here the code:

- (void)requireObjects{

    @try {
        //threadsQueue is a NSOperationQueue allocated and initialized in viewDidLoad method
        [threadsQueue cancelAllOperations];
        [threadsQueue waitUntilAllOperationsAreFinished];



                [_arrID removeAllObjects];
                [_arrNames removeAllObjects];
                [_arrStyle removeAllObjects];
                [_arrLocation removeAllObjects];
                [_arrProfileSnaps removeAllObjects];

            _arrNames = [[NSMutableArray alloc] init];
            _arrStyle = [[NSMutableArray alloc] init];
            _arrLocation = [[NSMutableArray alloc] init];
            _arrProfileSnaps = [[NSMutableArray alloc] init];

        [threadsQueue addOperation:[NSBlockOperation blockOperationWithBlock: ^{

            [[NSOperationQueue mainQueue] addOperationWithBlock:^{

                CGRect activityFrame = CGRectMake(self.view.center.x, self.view.center.y, 0.0, 0.0);

                _activityIndicator = [[UIActivityIndicatorView alloc] initWithFrame:activityFrame];

                [[self.view superview] addSubview:_activityIndicator];

                _activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhiteLarge;
                _activityIndicator.color = [UIColor whiteColor];
                [_activityIndicator startAnimating];
                [_tableView reloadData];
            }];


        _arrID = [[NSMutableArray alloc] initWithArray:[NSArray arrayWithObjects:@"0",@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9", nil]];

            for (int i = 0; i < [_arrID count]; i++) {
                [_arrStyle addObject:@“..”];
                [_arrNames addObject:@".."];
                [_arrLocation addObject:@“..”];
                [_arrProfileSnaps addObject:[UIImage imageNamed:@"blank"]];
            }

            [[NSOperationQueue mainQueue] addOperationWithBlock: ^{

                [self.tableView reloadData];
                [_activityIndicator stopAnimating];
            }];
        }]];
    }

    @catch (NSException *exception) {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"An exception has occurred" message:[NSString stringWithFormat:@"%@",exception] delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:nil, nil];
        [alert show];
    }
}

The app crashes in one iteration of the for loop at the point where I do [_arrNames insertObject:.... The error:

Terminating app due to uncaught exception 'NSRangeException', reason: '* -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'

The strange thing is that the method succeeds any time I call it, but crashes only when I call it while it's already running!

Pinturikkio
  • 1,490
  • 1
  • 14
  • 28
  • You can't comment out the way you're filling arrays in a question with an array index out of bounds error and expect to get any help. – nhgrif May 30 '14 at 11:30
  • I can't show you how I fill my array, but I said that the array is properly filled.. I told.. I checked everything, even with NSLog.. – Pinturikkio May 30 '14 at 11:33
  • 2
    It's clearly NOT filled properly. It's empty at some point when you're expected it to be not empty. – nhgrif May 30 '14 at 11:34
  • add Exception Breakpoint first. Then debug your code properly and see that your arrays have objects.. Exception Breakpoint will tell you exact location (array) of crash. The problem is within your array.. – Salman Zaidi May 30 '14 at 11:37
  • I've already tried this... Nothing – Pinturikkio May 30 '14 at 11:40
  • Ok see edit in the code.. It's the same also if I fill the arrNames with an empty string! – Pinturikkio May 30 '14 at 12:12
  • Look arrID is filled by 10 string objects.. Now who solve my problem? – Pinturikkio May 30 '14 at 12:15

1 Answers1

1

You are calling [_arrID removeAllObjects]; and the same for _arrNames, etc. on an operation queue, and this could run concurrently depending on which thread requireObjects: is called on and is not necessarily thread safe. Try initializing and setting up the objects before creating the block and use variable passing instead of communicating through variables stored in the object.

Peter DeWeese
  • 18,141
  • 8
  • 79
  • 101