Cocoa thread synchronisation when using [ALAssetsLibrary enumerateGroupsWithTypes:]

…衆ロ難τιáo~ 提交于 2019-11-28 21:37:53

The framework doesn't run these blocks on a separate thread. It just runs them as additional events in the same run-loop. To prove it, try this

    [library enumerateGroupsWithTypes:ALAssetsGroupAll 
                           usingBlock:[^(ALAssetsGroup * group, BOOL * stop)
                             {
                               if([NSThread isMainThread])
                               {
                                  NSLog(@"main");
                               }
                               else
                               {
                                 NSLog(@"non-main");
                               }
                             } copy] 
           failureBlock:^(NSError * err)
                          {NSLog(@"Erorr: %@", [err localizedDescription] );}];
    [library release];
    if([NSThread isMainThread])
    {
        NSLog(@"main");
    }
    else
    {
        NSLog(@"non-main");
    }

My output from this was

main
main
main

Meaning that the block was being called in the main thread. It's just a separate event. To solve your problem, you just need to return your value somehow from within the block when you reach the last step. You can tell it's the last step because your block will be called with nil for the group object.

EDIT: for instance use this block

^(ALAssetsGroup * group, BOOL * stop)
{
    if(group == nil)
    {
        // we've enumerated all the groups 
        // do something to return a value somehow (maybe send a selector to a delegate)
    }
}

The answer is to use the NSConditionLock class thusly ...

typedef enum {
    completed = 0,
    running = 1
} threadState;

...

NSConditionLock *lock = [[NSConditionLock alloc] initWithCondition:running];

Then spin off your thread, or in my case a call to [ALAssetsLibrary enumerateGroupsWithTypes:]. Then block the parent thread with this ...

// Await completion of the worker threads 
[lock lockWhenCondition:completed];
[lock unlockWithCondition:completed];

When all work is done in the child/worker thread, unblock the parent with this ...

// Signal the waiting thread
[lock lockWhenCondition:running];
[lock unlockWithCondition:completed];

Simply use this:

[library enumerateGroupsWithTypes:ALAssetsGroupAll 
                           usingBlock:[^(ALAssetsGroup * group, BOOL * stop)
{
    if(group == nil)
    {
        // this is end of enumeration
    }
}
.
.
.
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!