- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
UICollectionView:我做错了。我只是不知道如何。
我在装有 iOS 6.0.1 的 iPhone 4S 上运行它。
我有一个 TableView ,其中一个部分专门用于图像:
当用户点击“添加图像...”单元格时,系统会提示他们从照片库中选择图像或使用相机拍摄新图像。应用程序的那部分似乎运行良好。
当用户第一次添加图像时,“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
总结:
-viewDidLoad
方法中实例化和配置-addImage:toCollectionView
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 仍然没有显示任何项目,所以我仍然做错了什么,我不知道是什么。
-numberOfItemsInSection:
。对不起小说的问题。有什么想法吗?
最佳答案
不幸的是,接受的答案是不正确的(尽管它在正确的轨道上);问题是当您应该刚刚插入该项目时,您正在调用 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/
我一直认为“throw”和“throw ex”的区别was that throw alone wasn't resetting the stacktrace of the exception. 不幸的
我需要处理这样的api错误代码,并为某些状态代码抛出错误。但是遵循代码显示了以上错误。我怎样才能做到这一点? func login(data: [String: Any], completion: @
我见过在 JavaScript 中抛出错误的 3 种不同方式: throw 'message'; throw Error('message'); throw new Error('message');
这个问题在这里已经有了答案: Exception handling : throw, throws and Throwable (8 个答案) 关闭 10 年前。 谁能简单介绍一下Java异常处理中
这是我的代码: func loadData() { ref.child(currentUserID!).observe(.childAdded) { (snapshot) in
可能很明显,但是我仍然无法理解throw和rethrow之间的区别,什么时候应该使用它们中的任何一个? 最佳答案 根据Effective Dart: If you decide to rethrow
这个问题在这里已经有了答案: "new" keyword in Scala (3 个答案) 关闭 5 年前。 在 Scala 中进行一些函数式编程,并且来自 Java 背景,我倾向于像这样抛出异常:
我有一个验证输入字符串的代码,如果输入字符串与所需的格式不匹配,我需要抛出 IllegalArgumentException,有多个字段,每个字段都有一组不同的验证条件,因此对于当前我正在执行的每个字
我的方法有一个抛出 NullPointerException 的返回类型。 public class Student { public String studentOne() {
有些帖子询问这两者之间的区别。 (为什么我要提这个...) 但我的问题在某种程度上有所不同,我在另一个错误神级处理方法中调用了“throw ex”。 public class Program {
谁能解释一下 throw、throws 和 Throwable 之间的区别以及何时使用哪个? 最佳答案 throws :在编写方法时使用,声明有问题的方法抛出了指定的(检查的)异常。 与检查的异常相反
我想知道编写异常收件箱和发件箱是否会改变特定程序的行为,例如 抛出 MyException(); 和 抛出(我的异常()); 我的代码: #include #include using names
抛出异常时,保留堆栈跟踪是最常见的期望行为,在 Java 中,这可以通过 throw ex; 获得,但在 C# 中,throw; 必须使用。 (另请注意,许多 C# 程序员经常错误地使用 throw
这个问题在这里已经有了答案: Exception handling : throw, throws and Throwable (8 个答案) 关闭 8 年前。 谁能举个例子说清楚Java异常处理中
这两个有什么区别吗? 最佳答案 异常是针对程序逻辑中的错误。 JVM 使用错误来表示环境有问题,例如 OutOfMemoryError 或 IncompatibleClassChangeError。
我试图到处寻找这个问题的答案,但似乎我运气不好。 我有一个非常简单的 Mongoose 模型 var userObject = { profile: { username: {
我遇到了这个重新抛出的异常,我很惊讶它甚至可以编译。 } catch(SomeException e) { ... throw(e); } 这个throw()和平时用的有什么区别吗?.
想象两段相似的代码: try { [...] } catch (myErr &err) { err.append("More info added to error..."); throw
我试图弄清楚Java中方法签名中的抛出和抛出语句之间的区别。方法签名中的抛出如下: public void aMethod() throws IOException{ FileReader f
这个问题在这里已经有了答案: throw Error('msg') vs throw new Error('msg') (2 个回答) 24 天前关闭。 没有 new 时抛出错误有什么缺点吗?关键词?
我是一名优秀的程序员,十分优秀!