I've struggled with this error hours, and finally I drill down to this piece of code. This code works well when you "Run" the app, but will cause app crashes when "Test". I've googled and found this question:
Occasional errors when running OCUnit application test suite on device
But the solution doesn't work for me ;-(
I am a newbie iOS developer, so I'm not sure if this piece of code does something evil. Can anybody tell me:
application:didFinishLaunchingWithOptions:
method? Thanks!
#import "BRAppDelegate.h"
#import <AssetsLibrary/AssetsLibrary.h>
@implementation BRAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(void) {
ALAssetsLibrary *lib = [ALAssetsLibrary new];
[lib enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop){
[group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop){
}];
} failureBlock:^(NSError *error){
}];
});
return YES;
}
The strangest thing is that if I comment out
[group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop){
}];
No crash occurs!
ALAssetLibrary isn't safe to run on any thread but the main thread. You use GCDD todispatch it to the background and therefore run in another thread.
read: http://death-mountain.com/2011/05/alassetslibrary-and-threads/
also take race to avoid mutating the asset library while enumerating it. that'd be bad too: Has anyone experienced crashes when using ALAssetsLibrary in a background thread?
you allocate it in a block.. a new one: but in a block so it goes away after the block is done because nobody else is holding on to it.
move the allocation of lib
into the main thread and save it as a member variable in the app delegate
so:
// Override point for customization after application launch.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(void) {
ALAssetsLibrary *lib = [ALAssetsLibrary new];
becomes:
@implementation AppDelegate {
ALAssetsLibrary *_lib;
}
...
// Override point for customization after application launch.
_lib = [ALAssetsLibrary new];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(void) {
我通过删除DerivedData
文件夹清除Xcode的缓存来解决此问题。
rm -rf ~/Library/Developer/Xcode/DerivedData/
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.