简体   繁体   中英

App crashes when run unittest due to 'objc_getClassList returned more classes than it should have.'

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:

  1. Is it OK to do the job like in the application:didFinishLaunchingWithOptions: method?
  2. Why does this piece code throw the error?

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;
}

EDIT

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?


BUT the main problem is how you use the lib I think...

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM