Ios 我的照片库似乎返回了错误的照片编号
当我使用AlassetLibrary获取本地照片时,效果很好。但当我用“照片”应用程序删除一些照片后,我的应用程序崩溃了 事故信息为:Ios 我的照片库似乎返回了错误的照片编号,ios,ipad,photos,alassetslibrary,Ios,Ipad,Photos,Alassetslibrary,当我使用AlassetLibrary获取本地照片时,效果很好。但当我用“照片”应用程序删除一些照片后,我的应用程序崩溃了 事故信息为: “由于未捕获的异常“NSRangeException”而终止应用程序,原因:'***-[NSOrderedSet EnumerateObjectsIndexes:options:usingBlock::]:索引14超出边界[0..9]'”'14' 看起来本地照片的数量仍然和以前一样。即使在我退出并重新启动应用程序后,它仍然会崩溃 本地照片访问代码: dispat
“由于未捕获的异常“NSRangeException”而终止应用程序,原因:'***-[NSOrderedSet EnumerateObjectsIndexes:options:usingBlock::]:索引14超出边界[0..9]'”'14'
看起来本地照片的数量仍然和以前一样。即使在我退出并重新启动应用程序后,它仍然会崩溃
本地照片访问代码:
dispatch_async(dispatch_get_main_queue(), ^
{
@autoreleasepool
{
ALAssetsLibraryAccessFailureBlock failureblock = ^(NSError *myerror)
{
NSLog(@"error occour =%@", [myerror localizedDescription]);
};
ALAssetsGroupEnumerationResultsBlock groupEnumerAtion = ^(ALAsset *result, NSUInteger index, BOOL *stop)
{
if (result!=NULL)
{
if ([[result valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypePhoto])
{
[self.g_imageArray addObject:result];
}
}
};
ALAssetsLibraryGroupsEnumerationResultsBlock
libraryGroupsEnumeration = ^(ALAssetsGroup* group, BOOL* stop)
{
if (group == nil)
{
return;
}
if (group!=nil) {
[group enumerateAssetsUsingBlock:groupEnumerAtion];
}
[self updatephotoList];
};
self.library = [[ALAssetsLibrary alloc] init];
[self.library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos
usingBlock:libraryGroupsEnumeration
failureBlock:failureblock];
}
});
如果我用系统摄像头拍摄另一张照片,我的应用程序会再次正常运行。您需要注册一名观察员,以获得库更改通知。发出通知时,重新计算AssetLibrary的组和内容。如果不注册通知,应用程序将获得库的旧快照,枚举将失败。
还请注意,在iOS 5.x下有一个关于
AlassetLibraryChangedNotification
的bug,如本文所述:注册观察员对我的情况没有帮助。用户仍在崩溃,但我没有。直到今天
我想出了解决这次车祸的办法。这最终是苹果照片库中的一个缺陷,但有一个解决办法。您要做的是,将过滤器设置为photo,然后设置为video,而不是将其保留为默认的“assets”。然后,每一次枚举一次,并进行一些技巧,以确保在执行任何需要的更新时获得最终的“空”点。我目前的方法有点混乱,但你明白了:
// pending is used to tell the block we're not done, even if result is NULL
BOOL pending = YES;
// resorted is just a flag I use in case there are no videos; if there are none, the block is never called at all, and thus the == NULL part never triggers
__block BOOL resorted = NO;
ALAssetsGroupEnumerationResultsBlock assetEnumerator = ^(ALAsset *result, NSUInteger index, BOOL *stop) {
if(result != NULL) {
[assets addObject:result];
} else if (! pending) {
// ready!!
resorted = YES;
[self resort]; // my own method; replace with e.g. tableView reload!
}
};
// there are two types of assets - photos and videos; we start with photo
[group setAssetsFilter:[ALAssetsFilter allPhotos]];
NSLog(@"assets = %d", group.numberOfAssets);
[group enumerateAssetsUsingBlock:assetEnumerator];
// we then set pending to NO; even though the enumeration happens in a separate thread, it seems like pending is not caught by the above enumeration (I have 105 images in the group I am enumerating, FWIW; it may be better to set pending in the == NULL part of the enumeration though
pending = NO;
// now we switch to video and do the same thing
[group setAssetsFilter:[ALAssetsFilter allVideos]];
BriefLog(@"assets = %d", group.numberOfAssets);
[group enumerateAssetsUsingBlock:assetEnumerator];
// if there are 0 vids, the above block is not ever called so we flip to a background thread and then back (probably not necessary) and then check if resorted is set; if it isn't we call resort
if (! resorted) dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^{
if (! resorted) {
[self resort]; // my own method; replace with e.g. tableView reload!
}
});
});
就这样。例外情况消失了。至少在我的情况下,他们做到了 这似乎是一个iOS错误,就像你说的那样,库返回了错误数量的照片,所以你得到了索引越界错误。解决方法是重新加载照片,如下所示:
ALAssetsLibraryGroupsEnumerationResultsBlock
libraryGroupsEnumeration = ^(ALAssetsGroup* group, BOOL* stop)
{
if (group == nil)
{
return;
}
//Force to reload photo as numberOfAssets is broken
NSLog(@"how many picture I have in this group: %d",[group numberOfAssets]);
[group setAssetsFilter:[ALAssetsFilter allPhotos]];//this will cause group to reload
NSLog(@"how many picture I have in this group: %d",[group numberOfAssets]);
if (group!=nil) {
[group enumerateAssetsUsingBlock:groupEnumerAtion];
}
[self updatephotoList];
};
我一开始是用秋朗的回答,但对我来说不起作用。 对我来说,有效的方法是在开始枚举之前,使用所有过滤器组合连续调用SetAssetFilter 3次
[group setAssetsFilter:[ALAssetsFilter allPhotos]];
[group setAssetsFilter:[ALAssetsFilter allVideos]];
[group setAssetsFilter:[ALAssetsFilter allAssets]];
在iOS 8上,我还注意到numberOfAssets返回了错误数量的照片,如果其中一些照片被删除,并且当前位于“最近删除的”相册中。对于那些使用所有AlassetRepresentation填充某些NSArray并且不想对代码进行太多更改的人,只需使用此检查器筛选阵列即可-
干杯 ALAssetsLibrary库在PHAssetsLibrary上被定价,因此请使用以下代码:
__block PHAssetCollection *collection;
_arr_downloadedWallpaper = [[NSMutableArray alloc] init];
// Find the album
PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];
fetchOptions.predicate = [NSPredicate predicateWithFormat:@"title = %@", @"Bhakti Ras"];
collection = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum
subtype:PHAssetCollectionSubtypeAny
options:fetchOptions].firstObject;
PHFetchResult *collectionResult = [PHAsset fetchAssetsInAssetCollection:collection options:nil];
[collectionResult enumerateObjectsUsingBlock:^(PHAsset *asset, NSUInteger idx, BOOL *stop) {
//add assets to an array for later use in the uicollectionviewcell
NSLog(@"asset is =%@",asset);
if (asset) {
[self.arr_downloadedWallpaper addObject:asset];
}
}];
如果您当前正在查看的相册被删除,则不会有帮助。是的,您将收到一个通知,但当尝试重新枚举时,应用程序将因
NSRangeException
异常而崩溃。即使没有后台更改,iOS 8(GM)上的numberOfAssets
也可能出错。是的,这是一个错误。不幸的是,numberOfAssets包含了iOS 8(GM)上被丢弃/删除的照片数量。numberOfAssets在iOS 8.0.2下似乎再次正确。您的pending=NO代码>无效。块按创建时的值捕获非\uu块
局部变量。我很确定其中一个调用得到了是,另一个得到了否。将必须仔细检查。不是真正的答案,而是注释。我也有同样的问题,它在iOS 8.0.2中对我进行了修复,numberOfAssets在iOS8.0.2上仍然出错。这或在调用之间添加numberOfAssets
对我获得正确的照片计数很有效。有一个问题:您确定[self-updatephotoList]
将在[group EnumerateAssetsingBlock…]的最后一个枚举块之后调用[self-updatephotoList]
?我的应用程序中有几十个崩溃,因此我将检查这种方法,看看它是如何工作的: