当我使用ALAssetsLibrary得到当地的照片,它工作正常。 但之后,我删除一些照片与“照片”应用我的应用程序崩溃。
崩溃的信息是:
"Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSOrderedSet enumerateObjectsAtIndexes:options:usingBlock:]: index 14 beyond bounds [0 .. 9]'".'14'
它看起来像局部照片数量仍然一样befoore。 而且即使我退出我的应用程序,并再次重新启动它,它仍然崩溃。
当地照片访问代码:
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];
}
});
如果我采取与系统相机另一张照片中,我的应用程序再次确定呢。
这似乎是在iOS漏洞,就像你说的ALAssetsLibrary返回错号码照片,使你有索引越界的错误。 解决方法是重新加载你的照片像这样的:
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];
};
注册一个观察者在我的情况没有帮助。 用户仍然崩溃,但我没有。 直到今天。
我想通了,解决这个崩溃的方式。 它到底在苹果的照片库中的缺陷,但有一个变通方法。 你要做的就是,你的过滤器设置为照片,然后到视频,而不是在默认的“资产”离开它。 然后,您枚举它每进行一次,并做一些挂羊头卖狗肉,以确保您获得最终的“在零”点做任何你需要更新。 我目前的做法是有点混乱,但你的想法:
// 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!
}
});
});
而已。 该NSRangeExceptions走开。 至少在我的情况下,他们做到了。
你需要什么是注册一个观察员ALAssetsLibraryChangedNotification
得到图书馆的变化。 当通知火灾,重新枚举组和AssetsLibrary的内容。 如果你不为通知注册您的应用程序将获得库的一个旧的快照和枚举将失败。 另请注意,关于一个bug ALAssetsLibraryChangedNotification
下的iOS 5.x的如下记载: http://www.openradar.me/10484334
我开始了Qiulang答案,但它并没有为我工作。 什么工作对我来说是调用setAssetsFilter连续3次,所有的过滤器组合,开始统计前。
[group setAssetsFilter:[ALAssetsFilter allPhotos]];
[group setAssetsFilter:[ALAssetsFilter allVideos]];
[group setAssetsFilter:[ALAssetsFilter allAssets]];
在iOS的8我还注意到,numberOfAssets返回错误数量的照片,如果他们中的一些被删除,位于“最近删除”专辑目前。
对于那些你谁填补一些的NSArray所有的ALAssetRepresentations和不想太多改变你的代码,只需使用此检查过滤你的阵列- AssetURLChecker
干杯!
ALAssetsLibrary库depriciated上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];
}
}];