UICollectionView insertItemsAtIndexPaths:抛出异常(UICollectionView insertItemsAtIndexPaths: throws exception)
UICollectionView:我做错了。 我只是不知道如何。
我的设置
我在带有iOS 6.0.1的iPhone 4S上运行它。
我的目标
我有一个表视图,其中一个部分专门用于图像:
当用户点击“添加图像...”单元格时,系统会提示他们从照片库中选择图像或使用相机拍摄新照片。 应用程序的这部分似乎工作正常。
当用户首次添加图像时,将从第二个表格单元格中删除“无图像”标签,并在其位置添加以编程方式创建的UICollectionView。 那部分似乎也运作良好。
集合视图应该显示他们添加的图像,它就在我遇到麻烦的地方。 (我知道随着图像数量的增长,我将不得不跳过一些箍来让桌面视图单元扩大。我还没那么远。)
当我尝试将项目插入到集合视图中时,它会抛出异常。 稍后会详细介绍。
我的代码
我有UITableViewController负责表视图也充当集合视图的委托和数据源。 这是相关代码(我省略了我认为与此问题无关的控制器位,包括
-viewDidLoad
方法中的-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:
必须强制集合视图查询其数据源并意识到它没有项目。 或者其他的东西。 我猜想在这里。 但是,好吧,无论如何:集合视图在这一点上仍然没有显示任何项目,所以我仍然做错了什么,我不知道是什么。结论是
- 当我尝试将一个项目添加到新建和插入的集合视图时,我得到一个奇怪的例外...除非我在尝试插入之前调用
-numberOfItemsInSection:
- 即使我设法通过阴暗的解决方法超越异常,项目仍然不会显示在集合视图中。
对不起,小问题。 有任何想法吗?
UICollectionView: I'm doing it wrong. I just don't know how.
My Setup
I'm running this on an iPhone 4S with iOS 6.0.1.
My Goal
I have a table view in which one section is devoted to images:
When the user taps the "Add Image..." cell, they are prompted to either choose an image from their photo library or take a new one with the camera. That part of the app seems to be working fine.
When the user first adds an image, the "No Images" label will be removed from the second table cell, and a UICollectionView, created programmatically, is added in its place. That part also seems to be working fine.
The collection view is supposed to display the images they have added, and it's here where I'm running into trouble. (I know that I'm going to have to jump through some hoops to get the table view cell to enlarge itself as the number of images grows. I'm not that far yet.)
When I attempt to insert an item into the collection view, it throws an exception. More on that later.
My Code
I've got the UITableViewController in charge of the table view also acting as the collection view's delegate and datasource. Here is the relevant code (I have omitted the bits of the controller that I consider unrelated to this problem, including lines in methods like
-viewDidLoad
. I've also omitted most of the image acquisition code since I don't think it's relevant):#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
To summarize:
- The collection view is instantiated and configured in the
-viewDidLoad
method- The UIImagePickerDelegate method that receives the chosen image calls
-addImage:toCollectionView
- ...which creates a new image view to hold the image and adds it to the datasource array and collection view. This is the line that produces the exception.
- The UICollectionView datasource methods rely on the imageViews array.
The Exception
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).'
If I'm parsing this right, what this is telling me is that the (brand new!) collection view thinks it was created with a single item. So, I added a log to
-addImage:toCollectionView
to test this theory:NSLog(@"%d", [cv numberOfItemsInSection:0]);
With that line in there, the exception never gets thrown! The call to
-numberOfItemsInSection:
must force the collection view to consult its datasource and realize that it has no items. Or something. I'm conjecturing here. But, well, whatever: the collection view still doesn't display any items at this point, so I'm still doing something wrong and I don't know what.In Conclusion
- I get an odd exception when I attempt to add an item to a newly-minted-and-inserted collection view...except when I call
-numberOfItemsInSection:
before attempting insertion.- Even if I manage to get past the exception with a shady workaround, the items still do not show up in the collection view.
Sorry for the novel of a question. Any ideas?
原文:https://stackoverflow.com/questions/13392413
最满意答案
数据库和应用程序之间没有实时连接。
BindingSource
是内存数据缓存和UI之间的链接。 它对数据库一无所知。 LINQ to SQL的工作原理是将数据从数据库中提取到应用程序中。 应用程序必须发起请求。 数据库不会将更改推送到应用程序,因为它不知道可能正在使用该数据的应用程序。 可能存在单个应用程序的单个实例或多个应用程序的数百个用户。There is no live connection between the database and the application. The
BindingSource
is a link between the in-memory data cache and the UI. It knows nothing about the database. LINQ to SQL works by pulling data into the application from the database. The application has to initiate the request. The database doesn't push changes to the application because it has no idea what applications there are that may be using that data. There might be a single instance of a single application or hundreds of users of multiple applications.
相关问答
更多-
应该在表单加载事件之前激活数据绑定。 您遇到的问题是,由于数据绑定基础结构优化,对于不可见控件的绑定不会发生,直到它们第一次可见。 这可能是因为WF的设计者认为数据绑定将仅用于绑定数据属性(如Text等),并且对于不可见控件执行此操作没有意义。 如果你不害怕使用一些内部(或者用户HighCore会说hacks),那么下面的帮助将有助于解决你的问题(我们使用类似的东西多年): public static class ControlUtils { static readonly Action
下列中不属于面向对象的编程语言的是?[2022-05-30]
a数据库和应用程序之间没有实时连接。 BindingSource是内存数据缓存和UI之间的链接。 它对数据库一无所知。 LINQ to SQL的工作原理是将数据从数据库中提取到应用程序中。 应用程序必须发起请求。 数据库不会将更改推送到应用程序,因为它不知道可能正在使用该数据的应用程序。 可能存在单个应用程序的单个实例或多个应用程序的数百个用户。 There is no live connection between the database and the application. The BindingS ...这通过定义网格的Relations属性来工作。 This works by defining the Relations property of the grid.BindingList不支持搜索,因为是。 实际上, bindingSource1.SupportsSearching返回false。 Find函数适用于想要实现支持搜索的IBindingList接口的其他类。 要获得一个值,你应该做bindingSource1.ToList().Find("Bar",5); BindingList does not support searching, as is. In fact bindingSource1.SupportsSearching return ... 在对BindingSource执行大量更改之前,应该取消设置BindingSource上的RaiseListChangedEvents属性,并在完成后重置。 然后,您可以使用ResetBindings刷新绑定控件。 您还应该使用BeginUpdate / EndUpdate在列表框项目上包装大量操作,以避免重绘。 这很可能是造成经济放缓的主要因素。 Ok, solved it. I have to manipulate the underlying collection and then reset bin ...我想出了这个解决方案 首先直接将GetNextID()方法添加到表模型中: SELECT autoinc_next FROM information_schema.columns WHERE (table_name = 'Estagio') AND (column_name = 'ID') 而且我需要一个新的行来加我做的 EstagioTableAdapter ta = new EstagioTableAdapter (); nextID = ta.GetNextID( ...您可以编辑整个字符串。 。 我的意思是只使用str_replace函数 例如 $string = "skype,teamviwer,notepad"; $old_value = "skype"; $new_value = "facebook"; $new_string = str_replace($old_value,$new_value,$string); 然后只需将此新字符串更新为数据库表。 。 You can edit the whole string . . I mean just usin ...使用CurrencyManager控制绑定而不使用BindingSource(Control binding with CurrencyManager without BindingSource)[2022-03-30]
第一次更改后( dr["NAME"]= textBox1.Text; )从绑定引发OnListChanged / OnListChanged 。 第二个文本框和复选框听取此消息并正在更新那些值,但这些值是旧值。 Right answer has shown itself, 'cause i missed a little cue. That was using temp variables before changing the datarow field from the control values d ...您的问题只是从您正在通过的列表中删除项目。 如果从BindingSources列表中删除项目,则前面的项目将被移回一个索引,这意味着您将跳过已重新定位到从中删除项目的索引的项目。 最简单的解决方案是将计数器的增量移动到else块,以便计数器仅在未删除项目时递增,否则您希望再次检查相同的索引,因为新项目现在占用此索引。 Bonus-info:我建议看一下BindingList ,并考虑将其用作BindingSource的数据源而不是普通的List。 将BindingList与bindingsource ... 相关文章
更多- java Exception异常处理实例
- EXT4 Store Load For Gird Exception
- EXT4 Store Batch Sync Exception
- Hive 终端产生的问题 (Failed to start database 'metastore_db', see the next exception for details.)
- [Hadoop Err] Call to ? failed on local exception: java.net.NoRouteToHostException: No route to host
- 为什么执行JAVA程序时,会出现Exception in thread"main" java.lan
- Java基础:异常的限制
- Java 异常处理
- spring的jdbctemplet的queryforObject()有异常,不知道原因
- 在web应用中如何对异常进行处理
最新问答
更多- 您如何使用git diff文件,并将其应用于同一存储库的副本的本地分支?(How do you take a git diff file, and apply it to a local branch that is a copy of the same repository?)
- 将长浮点值剪切为2个小数点并复制到字符数组(Cut Long Float Value to 2 decimal points and copy to Character Array)
- OctoberCMS侧边栏不呈现(OctoberCMS Sidebar not rendering)
- 页面加载后对象是否有资格进行垃圾回收?(Are objects eligible for garbage collection after the page loads?)
- codeigniter中的语言不能按预期工作(language in codeigniter doesn' t work as expected)
- 在计算机拍照在哪里进入
- 使用cin.get()从c ++中的输入流中丢弃不需要的字符(Using cin.get() to discard unwanted characters from the input stream in c++)
- No for循环将在for循环中运行。(No for loop will run inside for loop. Testing for primes)
- 单页应用程序:页面重新加载(Single Page Application: page reload)
- 在循环中选择具有相似模式的列名称(Selecting Column Name With Similar Pattern in a Loop)
- System.StackOverflow错误(System.StackOverflow error)
- KnockoutJS未在嵌套模板上应用beforeRemove和afterAdd(KnockoutJS not applying beforeRemove and afterAdd on nested templates)
- 散列包括方法和/或嵌套属性(Hash include methods and/or nested attributes)
- android - 如何避免使用Samsung RFS文件系统延迟/冻结?(android - how to avoid lag/freezes with Samsung RFS filesystem?)
- TensorFlow:基于索引列表创建新张量(TensorFlow: Create a new tensor based on list of indices)
- 企业安全培训的各项内容
- 错误:RPC失败;(error: RPC failed; curl transfer closed with outstanding read data remaining)
- C#类名中允许哪些字符?(What characters are allowed in C# class name?)
- NumPy:将int64值存储在np.array中并使用dtype float64并将其转换回整数是否安全?(NumPy: Is it safe to store an int64 value in an np.array with dtype float64 and later convert it back to integer?)
- 注销后如何隐藏导航portlet?(How to hide navigation portlet after logout?)
- 将多个行和可变行移动到列(moving multiple and variable rows to columns)
- 提交表单时忽略基础href,而不使用Javascript(ignore base href when submitting form, without using Javascript)
- 对setOnInfoWindowClickListener的意图(Intent on setOnInfoWindowClickListener)
- Angular $资源不会改变方法(Angular $resource doesn't change method)
- 在Angular 5中不是一个函数(is not a function in Angular 5)
- 如何配置Composite C1以将.m和桌面作为同一站点提供服务(How to configure Composite C1 to serve .m and desktop as the same site)
- 不适用:悬停在悬停时:在元素之前[复制](Don't apply :hover when hovering on :before element [duplicate])
- 常见的python rpc和cli接口(Common python rpc and cli interface)
- Mysql DB单个字段匹配多个其他字段(Mysql DB single field matching to multiple other fields)
- 产品页面上的Magento Up出售对齐问题(Magento Up sell alignment issue on the products page)