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.