Array objectAtIndex: out of bounds error

2019-09-05 17:39发布

问题:

So recently, I was having trouble figuring out how to create a search bar for a uicollectionview (please look here). Luckily, someone was able to answer it for me. However, because the scrolling for my app was really slow and buggy, I decided to implement an asynchronous request to make the images load in background, and hence load, more quickly.

The problem is that my array that contains the search query cannot "reload" my uicollectionview because the asynchronous request is interfering with it. Or at least, that is what I think the problem is, if the problem lies somewhere else, please, tell me.

This is the error message that I keep getting:

2014-07-21 16:28:22.199 A Great App for TF2[545:70b] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
*** First throw call stack:
(
    0   CoreFoundation                      0x01c2e5e4 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x019b18b6 objc_exception_throw + 44
    2   CoreFoundation                      0x01bcf4e6 -[__NSArrayM objectAtIndex:] + 246
    3   CoreFoundation                      0x01cad608 -[NSArray objectAtIndexedSubscript:] + 40
    4   A Great App for TF2                 0x0001ebf1 __62-[MasterViewController collectionView:cellForItemAtIndexPath:]_block_invoke + 289
    5   Foundation                          0x016cd695 __67+[NSURLConnection sendAsynchronousRequest:queue:completionHandler:]_block_invoke_2 + 151
    6   Foundation                          0x0162d945 -[NSBlockOperation main] + 88
    7   Foundation                          0x01686829 -[__NSOperationInternal _start:] + 671
    8   Foundation                          0x01603558 -[NSOperation start] + 83
    9   Foundation                          0x01688af4 __NSOQSchedule_f + 62
    10  libdispatch.dylib                   0x063454b0 _dispatch_client_callout + 14
    11  libdispatch.dylib                   0x0633375e _dispatch_main_queue_callback_4CF + 340
    12  CoreFoundation                      0x01c93a5e __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 14
    13  CoreFoundation                      0x01bd46bb __CFRunLoopRun + 1963
    14  CoreFoundation                      0x01bd3ac3 CFRunLoopRunSpecific + 467
    15  CoreFoundation                      0x01bd38db CFRunLoopRunInMode + 123
    16  GraphicsServices                    0x02fce9e2 GSEventRunModal + 192
    17  GraphicsServices                    0x02fce809 GSEventRun + 104
    18  UIKit                               0x0071fd3b UIApplicationMain + 1225
    19  A Great App for TF2                 0x000235dd main + 141
    20  libdyld.dylib                       0x065d770d start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) 

My Code

This is quite long, as I use a long written api call to generate the cells in my collection view. I'll try to excise unnecessary parts of the code.

MasterViewController.m

@interface MasterViewController () <SteamManagerDelegate> {
    NSArray *_groups;
    NSArray *_itemGroups;
    NSArray *_backpackItems;
    NSArray *_backpackItemPhotos;
    SteamManager *_manager;

}

@property (nonatomic, strong) NSMutableArray *dataSource, *originalDataSource, *backpackSource;
@end

@implementation MasterViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.collectionView.dataSource = self;
    self.collectionView.delegate = self;
    self.automaticallyAdjustsScrollViewInsets = NO;

    UISearchBar *searchBar = [UISearchBar new];
    searchBar.delegate = self;
    searchBar.showsCancelButton = YES;
    self.navigationItem.titleView = searchBar;



    _manager = [[SteamManager alloc] init];

    _manager.communicator = [[SteamCommunicator alloc] init];
    _manager.communicator.delegate = _manager;
    _manager.delegate = self;
    [self startFetchingGroups];
    loadingView = [[UIView alloc] initWithFrame:CGRectMake(75, 155, 170, 170)];
    loadingView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
    loadingView.clipsToBounds = YES;
    loadingView.layer.cornerRadius = 10.0;

    activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
    activityView.frame = CGRectMake(65, 40, activityView.bounds.size.width, activityView.bounds.size.height);
    [loadingView addSubview:activityView];

    loadingLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 115, 130, 22)];
    loadingLabel.backgroundColor = [UIColor clearColor];
    loadingLabel.textColor = [UIColor whiteColor];
    loadingLabel.adjustsFontSizeToFitWidth = YES;
    loadingLabel.textAlignment  = UITextAlignmentCenter;
    loadingLabel.text = @"Loading...";
    [loadingView addSubview:loadingLabel];

    [self.view addSubview:loadingView];
    [activityView startAnimating];

}

#pragma mark - Notification Observer
- (void)startFetchingGroups
{
    [_manager fetchGroups];
}

#pragma mark - SteamManagerDelegate
- (void)didReceiveGroups:(NSArray *)groups
{
    _groups = groups;
}

- (void)didReceieveItemGroups:(NSArray *)groups
{
    _itemGroups = groups;
    _backpackItems = [self createBackpackIcons:_groups
                               usingItemGroups:_itemGroups];
    _dataSource = [[NSMutableArray alloc] init];

    for(NSUInteger i = 0; i < _backpackItems.count; i++){
        backpackIcons *items = _backpackItems[i];
        [_dataSource addObject:items.name];
    }
    self.originalDataSource = self.dataSource;



    dispatch_async(dispatch_get_main_queue(), ^{


        [self.collectionView reloadData];

        [activityView stopAnimating];
        [loadingView removeFromSuperview];
        });
}

#pragma mark - Collection View
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
        return _groups.count;
    }


- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    static NSString *identifier = @"Cell";
    backpackIcons *item = _backpackItems[indexPath.row];
    NSString *photoURL = item.image_url;
    NSString *quality = item.quality;
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
    UIImageView *itemImageView = (UIImageView *)[cell viewWithTag:100];
    UILabel *itemName = (UILabel *) [cell viewWithTag:110];

    NSLog([NSString stringWithFormat:@"%d", _dataSource.count]);
        //backpackIcons *item1 = _dataSource[indexPath.row];

    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:photoURL]];
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
        [itemImageView setImage:[UIImage imageWithData:data]];
        [itemName setText:_dataSource[indexPath.row]];


    }];

    /*itemImageView.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:photoURL]]];*/
    [itemImageView setBackgroundColor:Rgb2UIColor(60, 53, 46)];
    if([[NSString stringWithFormat:@"%@", quality] isEqualToString:@"6"])
    {
        [itemImageView.layer setBorderColor:[Rgb2UIColor(125, 109, 0) CGColor]];
    }
    else if([[NSString stringWithFormat:@"%@", quality] isEqualToString:@"1"])
    {
        [itemImageView.layer setBorderColor:[Rgb2UIColor(77, 116, 85) CGColor]];
    }
    else if ([[NSString stringWithFormat:@"%@", quality] isEqualToString:@"3"])
    {
        [itemImageView.layer setBorderColor:[Rgb2UIColor(71, 98, 145) CGColor]];
    }
    else if ([[NSString stringWithFormat:@"%@", quality] isEqualToString:@"5"])
    {
        [itemImageView.layer setBorderColor:[Rgb2UIColor(134, 80, 172) CGColor]];
    }
    else if ([[NSString stringWithFormat:@"%@", quality] isEqualToString:@"11"])
    {
        [itemImageView.layer setBorderColor:[Rgb2UIColor(207, 106, 50) CGColor]];
    }
    else if ([[NSString stringWithFormat:@"%@", quality] isEqualToString:@"7"] || [[NSString stringWithFormat:@"%@", quality] isEqualToString:@"9"])
    {
        [itemImageView.layer setBorderColor:[Rgb2UIColor(112, 176, 74) CGColor]];
    }
    else if ([[NSString stringWithFormat:@"%@", quality] isEqualToString:@"8"])
    {
        [itemImageView.layer setBorderColor:[Rgb2UIColor(165, 15, 121) CGColor]];
    }
    else if ([[NSString stringWithFormat:@"%@", quality] isEqualToString:@"0"])
    {
        [itemImageView.layer setBorderColor:[Rgb2UIColor(178, 178, 178) CGColor]];
    }
    else if ([[NSString stringWithFormat:@"%@", quality] isEqualToString:@"13"])
    {
        [itemImageView.layer setBorderColor:[Rgb2UIColor(56, 243, 171) CGColor]];
    }
    else
    {
        [itemImageView.layer setBorderColor:[Rgb2UIColor(170, 0, 0) CGColor]];
    }
        [itemImageView.layer setBorderWidth: 1.0];

    return cell;
}

#pragma mark UISearchBarDelegate

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
    [self applyFilters:[NSSet setWithObject:searchBar.text]];
    [searchBar resignFirstResponder];
}

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
    [searchBar resignFirstResponder];
}

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
    if (![searchText length]) {
        self.dataSource = self.originalDataSource;
        [self.collectionView reloadData];
    }
}

#pragma mark private

- (void)applyFilters:(NSSet *)filters {
    NSMutableArray *newData = [NSMutableArray array];
    for (NSString *s in self.dataSource) {
        for (NSString *filter in filters) {
            if ([s rangeOfString:filter].location != NSNotFound) {
                [newData addObject:s];
                break;
            }
        }
    }
    self.dataSource = newData;

    [self.collectionView reloadData];
}

If you would like to download my project to view the file separate, please visit here. The class is called MasterViewController.m.

Any help would be greatly appreciated.