【发布时间】:2012-11-15 06:12:50
【问题描述】:
UICollectionView:我做错了。我只是不知道怎么做。
我的设置
我在装有 iOS 6.0.1 的 iPhone 4S 上运行它。
我的目标
我有一个表格视图,其中一个部分专门用于图像:
当用户点击“添加图片...”单元格时,系统会提示他们从照片库中选择一张图片或使用相机拍摄一张新图片。应用程序的这一部分似乎运行良好。
当用户第一次添加图像时,“无图像”标签将从第二个表格单元格中删除,并在其位置添加以编程方式创建的 UICollectionView。这部分似乎也运行良好。
集合视图应该显示他们添加的图像,而我在这里遇到了麻烦。 (我知道随着图像数量的增加,我将不得不跳过一些障碍来让表格视图单元格自行放大。我还没有那么远。)
当我尝试将一个项目插入到集合视图中时,它会引发异常。稍后会详细介绍。
我的代码
我有负责表格视图的 UITableViewController 也充当集合视图的委托和数据源。这是相关代码(我省略了我认为与此问题无关的控制器位,包括-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
总结一下:
- 集合视图在
-viewDidLoad方法中实例化和配置 - 接收所选图像的 UIImagePickerDelegate 方法调用
-addImage:toCollectionView - ...创建一个新的图像视图来保存图像并将其添加到数据源数组和集合视图中。这是产生异常的行。
- UICollectionView 数据源方法依赖于 imageViews 数组。
例外
由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'无效更新:第0节中的项目数无效。更新后现有节中包含的项目数(1)必须等于项目数更新前包含在该节中的项目数 (1),加上或减去从该节插入或删除的项目数(1 插入,0 删除),加上或减去移入或移出该节的项目数(0 移入, 0 移出)。'
如果我的解析正确,这告诉我的是(全新的!)集合视图认为它是用单个项目创建的。所以,我给-addImage:toCollectionView加了一个日志来测试这个理论:
NSLog(@"%d", [cv numberOfItemsInSection:0]);
有了那一行,异常就不会被抛出!对-numberOfItemsInSection: 的调用必须强制集合视图查询其数据源并意识到它没有项目。或者其他的东西。我在这里推测。但是,好吧,无论如何:此时集合视图仍然没有显示任何项目,所以我仍然做错了什么,我不知道是什么。
结论
- 当我尝试将项目添加到新创建和插入的集合视图时遇到一个奇怪的异常...除非我在尝试插入之前调用
-numberOfItemsInSection:。 - 即使我设法通过一个隐蔽的解决方法克服了异常,这些项目仍然不会显示在集合视图中。
对不起,小说的问题。有什么想法吗?
【问题讨论】:
-
我唯一能建议的就是在
[imageViews addObject:imageView];和-numberOfItemsInSection之后添加一个NSLog语句。这将准确地告诉您您的数组是否是它应该是的,以及是否在正确的时刻调用了numberOfItemsInSection。
标签: ios uiimageview uicollectionview