使用[ALAssetsLibrary enumerateGroupsWithTypes:]时的Cocoa线程同步

时间:2010-08-27 18:00:30

标签: iphone objective-c cocoa-touch nslock

我最近和一些人一样,发现 [ALAssetsLibrary enumerateGroupsWithTypes] 喜欢在另一个线程上运行它的块。 Apple没有证明这一点真是太可惜了: - )

在我目前的情况下,我需要在主线程返回任何结果之前等待枚举完成。我显然需要某种线程同步。

我读过关于NSLock& NSConditionLock,但似乎没有任何东西符合“发出此工作线程已完成的阻塞线程信号”的要求。这似乎是一个足够简单的需求 - 有人能指出我正确的方向吗?

你的线索&嘘声,一如既往地受到欢迎,

微米。

3 个答案:

答案 0 :(得分:11)

框架不会在单独的线程上运行这些块。它只是在同一个运行循环中将它们作为附加事件运行。要证明这一点,试试这个

    [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");
    }

我的输出是

main
main
main

意味着在主线程中调用了块。这只是一个单独的事件。 要解决您的问题,您只需要在到达最后一步时从块内以某种方式返回您的值。您可以告诉它是最后一步,因为对于组对象,将使用nil调用块。

编辑:例如使用此块

^(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)
    }
}

答案 1 :(得分:2)

答案是使用NSConditionLock类......

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

...

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

然后分离你的线程,或者在我的情况下调用[ALAssetsLibrary enumerateGroupsWithTypes:]。然后使用this ...

阻止父线程
// Await completion of the worker threads 
[lock lockWhenCondition:completed];
[lock unlockWithCondition:completed];

如果所有工作都在子/工作人员主题中完成,请使用此功能解锁父级...

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

答案 2 :(得分:2)

只需使用:

[library enumerateGroupsWithTypes:ALAssetsGroupAll 
                           usingBlock:[^(ALAssetsGroup * group, BOOL * stop)
{
    if(group == nil)
    {
        // this is end of enumeration
    }
}
.
.
.