gpt4 book ai didi

ios - UICollectionView insertItemsAtIndexPaths : throws exception

转载 作者:可可西里 更新时间:2023-11-01 05:04:44 30 4
gpt4 key购买 nike

UICollectionView:我做错了。我只是不知道如何。

我的设置

我在装有 iOS 6.0.1 的 iPhone 4S 上运行它。

我的目标

我有一个 TableView ,其中一个部分专门用于图像:Screen shot of the table view section

当用户点击“添加图像...”单元格时,系统会提示他们从照片库中选择图像或使用相机拍摄新图像。应用程序的那部分似乎运行良好。

当用户第一次添加图像时,“No Images”标签将从第二个表格单元格中移除,并在其位置添加以编程方式创建的 UICollectionView。该部分似乎也工作正常。

Collection View 应该显示他们添加的图像,而这正是我遇到麻烦的地方。 (我知道我将不得不跳过一些障碍,让表格 View 单元随着图像数量的增加而自行放大。我还没到那一步。)

当我试图将一个项目插入 Collection View 时,它抛出一个异常。稍后会详细介绍。

我的代码

我让 UITableViewController 负责 TableView ,同时充当 Collection View 的委托(delegate)和数据源。这是相关代码(我省略了我认为与此问题无关的 Controller 位,包括方法中的行,如 -viewDidLoad。我也省略了大部分图像采集代码,因为我不认为它是相关的):

#define ATImageThumbnailMaxDimension 100

@interface ATAddEditActivityViewController ()
{
UICollectionView* imageDisplayView;
NSMutableArray* imageViews;
}

@property (weak, nonatomic) IBOutlet UITableViewCell *imageDisplayCell;
@property (weak, nonatomic) IBOutlet UILabel *noImagesLabel;
@end

@implementation ATAddEditActivityViewController

- (void)viewDidLoad
{
[super viewDidLoad];

UICollectionViewFlowLayout* flowLayout = [[UICollectionViewFlowLayout alloc] init];
flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical;

imageDisplayView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, 290, 120) collectionViewLayout:flowLayout]; // The frame rect still needs tweaking
imageDisplayView.delegate = self;
imageDisplayView.dataSource = self;
imageDisplayView.backgroundColor = [UIColor yellowColor]; // Just so I can see the actual extent of the view
imageDisplayView.opaque = YES;
[imageDisplayView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"Cell"];

imageViews = [NSMutableArray array];
}

#pragma mark - UIImagePickerDelegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
/* ...code defining imageToSave omitted... */

[self addImage:imageToSave toCollectionView:imageDisplayView];


[self dismissModalViewControllerAnimated:YES];
}

#pragma mark - UICollectionViewDelegate
- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}

#pragma mark - UICollectionViewDatasource
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
[[cell contentView] addSubview:imageViews[indexPath.row]];
return cell;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return [imageViews count];
}

#pragma mark - UICollectionViewDelegateFlowLayout
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return ((UIImageView*)imageViews[indexPath.item]).bounds.size;
}

#pragma mark - Image Handling
- (void)addImage:(UIImage*)image toCollectionView:(UICollectionView*)cv
{
if ([imageViews count] == 0) {
[self.noImagesLabel removeFromSuperview];
[self.imageDisplayCell.contentView addSubview:cv];
}

UIImageView* imageView = [[UIImageView alloc] initWithImage:image];
/* ...code that sets the bounds of the image view omitted... */

[imageViews addObject:imageView];
[cv insertItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:[imageViews count]-1 inSection:0]]];
[cv reloadData];
}

@end

总结:

  • Collection View 在-viewDidLoad方法中实例化和配置
  • 接收所选图像调用的 UIImagePickerDelegate 方法 -addImage:toCollectionView
  • ...创建一个新的 ImageView 来保存图像并将其添加到数据源数组和 Collection View 中。这是产生异常的行。
  • UICollectionView 数据源方法依赖于 imageViews 数组。

异常

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of items in section 0. The number of items contained in an existing section after the update (1) must be equal to the number of items contained in that section before the update (1), plus or minus the number of items inserted or deleted from that section (1 inserted, 0 deleted) and plus or minus the number of items moved into or out of that section (0 moved in, 0 moved out).'

如果我解析正确,这告诉我的是(全新!) Collection View 认为它是用单个项目创建的。所以,我在 -addImage:toCollectionView 中添加了一个日志来测试这个理论:

NSLog(@"%d", [cv numberOfItemsInSection:0]);

有了那一行,就永远不会抛出异常!对 -numberOfItemsInSection: 的调用必须强制 Collection View 查询其数据源并意识到它没有项目。或者其他的东西。我在这里猜测。但是,好吧,无论如何:此时 Collection View 仍然没有显示任何项目,所以我仍然做错了什么,我不知道是什么。

总结

  1. 当我尝试将项目添加到新创建和插入的 Collection View 时出现奇怪的异常...除非我在尝试插入之前调用 -numberOfItemsInSection:
  2. 即使我设法通过阴暗的解决方法克服了异常,这些项目仍然没有显示在 Collection View 中。

对不起小说的问题。有什么想法吗?

最佳答案

不幸的是,接受的答案是不正确的(尽管它在正确的轨道上);问题是当您应该刚刚插入该项目时,您正在调用 reloadData & insertItems。所以不是:

[imageViews addObject:imageView];
[cv insertItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:[imageViews count]-1 inSection:0]]];
[cv reloadData];

只是做:

[imageViews addObject:imageView];
[cv insertItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:[imageViews count]-1 inSection:0]]];

这不仅会给你一个漂亮的动画,它可以防止你低效地使用 tableview(在 1-cell Collection View 中不是什么大问题,但对于更大的数据集来说是一个大问题),并避免像那个那样的崩溃您看到的是,两种方法都试图修改 Collection View (其中一种方法 -- reloadData -- 不能很好地与其他方法一起使用)。

顺便说一句,reloadData 对 UICollectionView 不是很友好;如果您确实有一个相当大的和/或复杂的集合,并且插入发生在调用 reloadData 之前或之后不久,插入可能会在 reloadData 完成之前完成——这将可靠地导致“无效的项目数”崩溃(同样如此删除)。调用 reloadSections 而不是仅仅调用 reloadData 似乎有助于避免该问题。

关于ios - UICollectionView insertItemsAtIndexPaths : throws exception,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13392413/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com