CollectionViewController.m line 439 __50-[CollectionViewController photoLibraryDidChange:]_block_invoke
致命异常:NSInternalInconsistencyException 尝试删除并重新加载相同的索引路径 ({length = 2, path = 0 - 26007})
- (void)photoLibraryDidChange:(PHChange *)changeInstance
{
// Call might come on any background queue. Re-dispatch to the main queue to handle it.
dispatch_async(dispatch_get_main_queue(), ^{
// check if there are changes to the assets (insertions, deletions, updates)
PHFetchResultChangeDetails *collectionChanges = [changeInstance changeDetailsForFetchResult:self.assetsFetchResults];
if (collectionChanges) {
// get the new fetch result
self.assetsFetchResults = [collectionChanges fetchResultAfterChanges];
UICollectionView *collectionView = self.collectionView;
if (![collectionChanges hasIncrementalChanges] || [collectionChanges hasMoves]) {
// we need to reload all if the incremental diffs are not available
[collectionView reloadData];
} else {
// if we have incremental diffs, tell the collection view to animate insertions and deletions
[collectionView performBatchUpdates:^{
NSIndexSet *removedIndexes = [collectionChanges removedIndexes];
if ([removedIndexes count]) {
[collectionView deleteItemsAtIndexPaths:[removedIndexes aapl_indexPathsFromIndexesWithSection:0]];
}
NSIndexSet *insertedIndexes = [collectionChanges insertedIndexes];
if ([insertedIndexes count]) {
[collectionView insertItemsAtIndexPaths:[insertedIndexes aapl_indexPathsFromIndexesWithSection:0]];
}
NSIndexSet *changedIndexes = [collectionChanges changedIndexes];
if ([changedIndexes count]) {
[collectionView reloadItemsAtIndexPaths:[changedIndexes aapl_indexPathsFromIndexesWithSection:0]];
}
} completion:NULL];
}
[self resetCachedAssets];
}
});
}
我无法重现这个问题。可能是什么问题呢?非常感谢!
最佳答案
我今天能够重现这个。为此,您需要:
我发现了一个更新的代码,它似乎可以更好地处理这里的更新行为: https://developer.apple.com/library/ios/documentation/Photos/Reference/PHPhotoLibraryChangeObserver_Protocol/
但它仍然不能处理这种情况,也不能处理要删除的索引更大的情况(即由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'尝试从第 0 节中删除第 9 项,该节之前仅包含 9 个项目更新')。我创建了这个代码的更新版本,可以更好地处理这个问题,到目前为止我还没有崩溃。
func photoLibraryDidChange(changeInfo: PHChange!) {
// Photos may call this method on a background queue;
// switch to the main queue to update the UI.
dispatch_async(dispatch_get_main_queue()) {
// Check for changes to the list of assets (insertions, deletions, moves, or updates).
if let collectionChanges = changeInfo.changeDetailsForFetchResult(self.assetsFetchResult) {
// Get the new fetch result for future change tracking.
self.assetsFetchResult = collectionChanges.fetchResultAfterChanges
if collectionChanges.hasIncrementalChanges {
// Get the changes as lists of index paths for updating the UI.
var removedPaths: [NSIndexPath]?
var insertedPaths: [NSIndexPath]?
var changedPaths: [NSIndexPath]?
if let removed = collectionChanges.removedIndexes {
removedPaths = self.indexPathsFromIndexSetWithSection(removed,section: 0)
}
if let inserted = collectionChanges.insertedIndexes {
insertedPaths = self.indexPathsFromIndexSetWithSection(inserted,section: 0)
}
if let changed = collectionChanges.changedIndexes {
changedPaths = self.indexPathsFromIndexSetWithSection(changed,section: 0)
}
var shouldReload = false
if changedPaths != nil && removedPaths != nil{
for changedPath in changedPaths!{
if contains(removedPaths!,changedPath){
shouldReload = true
break
}
}
}
if removedPaths?.last?.item >= self.assetsFetchResult.count{
shouldReload = true
}
if shouldReload{
self.collectionView.reloadData()
}else{
// Tell the collection view to animate insertions/deletions/moves
// and to refresh any cells that have changed content.
self.collectionView.performBatchUpdates(
{
if let theRemovedPaths = removedPaths {
self.collectionView.deleteItemsAtIndexPaths(theRemovedPaths)
}
if let theInsertedPaths = insertedPaths {
self.collectionView.insertItemsAtIndexPaths(theInsertedPaths)
}
if let theChangedPaths = changedPaths{
self.collectionView.reloadItemsAtIndexPaths(theChangedPaths)
}
if (collectionChanges.hasMoves) {
collectionChanges.enumerateMovesWithBlock() { fromIndex, toIndex in
let fromIndexPath = NSIndexPath(forItem: fromIndex, inSection: 0)
let toIndexPath = NSIndexPath(forItem: toIndex, inSection: 0)
self.collectionView.moveItemAtIndexPath(fromIndexPath, toIndexPath: toIndexPath)
}
}
}, completion: nil)
}
} else {
// Detailed change information is not available;
// repopulate the UI from the current fetch result.
self.collectionView.reloadData()
}
}
}
}
func indexPathsFromIndexSetWithSection(indexSet:NSIndexSet?,section:Int) -> [NSIndexPath]?{
if indexSet == nil{
return nil
}
var indexPaths:[NSIndexPath] = []
indexSet?.enumerateIndexesUsingBlock { (index, Bool) -> Void in
indexPaths.append(NSIndexPath(forItem: index, inSection: section))
}
return indexPaths
}
Swift 3/iOS 10 版本:
func photoLibraryDidChange(_ changeInstance: PHChange) {
guard let collectionView = self.collectionView else {
return
}
// Photos may call this method on a background queue;
// switch to the main queue to update the UI.
DispatchQueue.main.async {
guard let fetchResults = self.fetchResults else {
collectionView.reloadData()
return
}
// Check for changes to the list of assets (insertions, deletions, moves, or updates).
if let collectionChanges = changeInstance.changeDetails(for: fetchResults) {
// Get the new fetch result for future change tracking.
self.fetchResults = collectionChanges.fetchResultAfterChanges
if collectionChanges.hasIncrementalChanges {
// Get the changes as lists of index paths for updating the UI.
var removedPaths: [IndexPath]?
var insertedPaths: [IndexPath]?
var changedPaths: [IndexPath]?
if let removed = collectionChanges.removedIndexes {
removedPaths = self.indexPaths(from: removed, section: 0)
}
if let inserted = collectionChanges.insertedIndexes {
insertedPaths = self.indexPaths(from:inserted, section: 0)
}
if let changed = collectionChanges.changedIndexes {
changedPaths = self.indexPaths(from: changed, section: 0)
}
var shouldReload = false
if let removedPaths = removedPaths, let changedPaths = changedPaths {
for changedPath in changedPaths {
if removedPaths.contains(changedPath) {
shouldReload = true
break
}
}
}
if let item = removedPaths?.last?.item {
if item >= fetchResults.count {
shouldReload = true
}
}
if shouldReload {
collectionView.reloadData()
} else {
// Tell the collection view to animate insertions/deletions/moves
// and to refresh any cells that have changed content.
collectionView.performBatchUpdates({
if let theRemovedPaths = removedPaths {
collectionView.deleteItems(at: theRemovedPaths)
}
if let theInsertedPaths = insertedPaths {
collectionView.insertItems(at: theInsertedPaths)
}
if let theChangedPaths = changedPaths {
collectionView.reloadItems(at: theChangedPaths)
}
collectionChanges.enumerateMoves { fromIndex, toIndex in
collectionView.moveItem(at: IndexPath(item: fromIndex, section: 0),
to: IndexPath(item: toIndex, section: 0))
}
})
}
} else {
// Detailed change information is not available;
// repopulate the UI from the current fetch result.
collectionView.reloadData()
}
}
}
}
func indexPaths(from indexSet: IndexSet?, section: Int) -> [IndexPath]? {
guard let set = indexSet else {
return nil
}
return set.map { (index) -> IndexPath in
return IndexPath(item: index, section: section)
}
}
关于ios - CRASH 尝试删除并重新加载相同的索引路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29337765/
我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.
我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为
查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html
我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的
我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下
我是Google云的新手,我正在尝试对其进行首次部署。我的第一个部署是RubyonRails项目。我基本上是在关注thisguideinthegoogleclouddocumentation.唯一的区别是我使用的是我自己的项目,而不是他们提供的“helloworld”项目。这是我的app.yaml文件runtime:customvm:trueentrypoint:bundleexecrackup-p8080-Eproductionconfig.ruresources:cpu:0.5memory_gb:1.3disk_size_gb:10当我转到我的项目目录并运行gcloudprevie
我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的
在Ruby中是否有Gem或安全删除文件的方法?我想避免系统上可能不存在的外部程序。“安全删除”指的是覆盖文件内容。 最佳答案 如果您使用的是*nix,一个很好的方法是使用exec/open3/open4调用shred:`shred-fxuz#{filename}`http://www.gnu.org/s/coreutils/manual/html_node/shred-invocation.html检查这个类似的帖子:Writingafileshredderinpythonorruby?
我正在尝试找到一种方法来规范化字符串以将其作为文件名传递。到目前为止我有这个:my_string.mb_chars.normalize(:kd).gsub(/[^\x00-\x7F]/n,'').downcase.gsub(/[^a-z]/,'_')但第一个问题:-字符。我猜这个方法还有更多问题。我不控制名称,名称字符串可以有重音符、空格和特殊字符。我想删除所有这些,用相应的字母('é'=>'e')替换重音符号,并将其余的替换为'_'字符。名字是这样的:“Prélèvements-常规”“健康证”...我希望它们像一个没有空格/特殊字符的文件名:“prelevements_routin