我整天都在处理这段代码,所以我可能会忽略一些愚蠢的东西,但我似乎无法找到问题,而且我的机智和#39;结束。
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
if(collectionView == self.titleBarCollectionView) {
return 1;
}
NSInteger photoCount = [[self.fetchedResultsController fetchedObjects] count];
NSInteger sectionCount = (photoCount + 3) / 3;
return sectionCount;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
if(collectionView != self.titleBarCollectionView) {
id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section];
NSInteger numberInSection = [sectionInfo numberOfObjects];
if(numberInSection < 3) numberInSection++;
return numberInSection;
}
return 3;
}
我有一个显示用户照片的UICollectionView。照片来自核心数据,但是集合视图中的第一个索引(第0项,第0部分)被替换为&#34;添加照片&#34;图像和所有照片indexPaths都经过调整以适应这种情况。它工作正常几个小时,但由于某些原因删除应用程序(重置核心数据)后,我似乎甚至无法加载视图。当它到达行* Terminating app due to uncaught exception 'NSRangeException', reason: '* -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'
时,它会立即崩溃,并显示错误id sectionInfo = [self.fetchedResultsController sections][section];
。我不能为我的生活弄清楚。以下是我的其他数据源方法。
-(void)configureCell:(UICollectionViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
if([cell.reuseIdentifier isEqualToString:@"Profile Title Cell"]) {
... Irrelevant code ...
} else if(indexPath.row == 0 && indexPath.section == 0) {
UIImageView *imageView = (UIImageView *)[cell viewWithTag:300];
imageView.image = [UIImage imageNamed:@"plusIcon.png"];
} else {
NSIndexPath *newIndexPath = [self newIndexPathFromIndexPath:indexPath];
Photo *photo = [self.fetchedResultsController objectAtIndexPath:newIndexPath];
UIImageView *imageView = (UIImageView *)[cell viewWithTag:300];
NSData *imageData = [[NSData alloc] initWithBase64EncodedString:photo.thumbnailData options:0];
imageView.image = [UIImage imageWithData:imageData];
if(photo.imageData) {
imageView.image = [UIImage imageWithData:photo.imageData];
} else if(photo.imageURL && ![photo.imageURL isEqualToString:@""]) {
NSString *imageURL = [NSString stringWithFormat:@"%@%@", PHOTOS_BASE_URL, photo.imageURL];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
self.activeThreads += 1;
NSData *imageURLData = [NSData dataWithContentsOfURL:[NSURL URLWithString:imageURL]];
dispatch_async(dispatch_get_main_queue(), ^{
photo.imageData = imageURLData;
[self.imageCollectionView reloadItemsAtIndexPaths:@[indexPath]];
self.activeThreads -= 1;
if(self.activeThreads < 1)
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
});
});
}
}
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = nil;
if(collectionView == self.titleBarCollectionView) {
cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Profile Title Cell" forIndexPath:indexPath];
} else {
cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Profile Image Cell" forIndexPath:indexPath];
}
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (NSIndexPath *)newIndexPathFromIndexPath:(NSIndexPath *)indexPath
{
NSInteger row = 0;
NSInteger section = 0;
if(indexPath.row > 0) {
row = indexPath.row - 1;
section = indexPath.section;
} else {
row = 2;
section = indexPath.section - 1;
}
return [NSIndexPath indexPathForItem:row inSection:section];
}
编辑:这是我的fetchedResultsController setter
- (NSFetchedResultsController *)fetchedResultsController
{
if(!_fetchedResultsController) {
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Photo"];
fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"uploadDate" ascending:YES]];
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"ownerID == %@", self.currentUser.userID];
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:[RKManagedObjectStore defaultStore].mainQueueManagedObjectContext
sectionNameKeyPath:@"sectionIdentifier"
cacheName:nil];
_fetchedResultsController.delegate = self;
[_fetchedResultsController performFetch:nil];
}
return _fetchedResultsController;
}
答案 0 :(得分:2)
您在评论中说fetchedObjects
会返回8个对象。在numberOfSectionsInCollectionView
中,您可以使用它来计算集合视图中的节数:
NSInteger photoCount = [[self.fetchedResultsController fetchedObjects] count];
NSInteger sectionCount = (photoCount + 3) / 3;
return sectionCount;
假设计数实际为8,则表示sectionCount
为3(11 / 3
,整数除法)。请注意,您不是要求获取的结果控制器它有多少部分,但是您告诉集合视图它应该有三个部分。
由于您返回上面的3,collectionView:numberOfItemsInSection:
将被调用3次,其中部分值为0,1和2.您将section
值传递给获取的结果控制器:
id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section];
仅当获取的结果控制器实际上有3个部分时才有效。 但你从来没有问过它有多少部分,所以不能保证它有那么多部分。在这种情况下,极有可能发生崩溃。
发生的事情是:
sectionNameKeyPath
[self.fetchedResultsController sections]
返回一个空数组因此你崩溃了。你不能告诉获取的结果控制器应该有多少部分。部分的数量取决于获取结果,除非您包含sectionNameKeyPath
,否则没有任何部分。
答案 1 :(得分:0)
事实证明collectionView:numberOfItemsInSection:
在NSFetchedResultsController
执行performFetch:
之前被调用,因此[self.fetchedResultsController sections]
为空。为了解决这个问题,我只需用一些简单的逻辑手动设置每个部分的项目数。
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
NSArray *fetchedObjects = [self.fetchedResultsController fetchedObjects];
NSInteger count = [fetchedObjects count] + 1;
NSInteger sections = count / 3;
if(sections > section) return 3;
else return count % 3;
}