Mar*_*wie 10 iphone cocoa-touch objective-c nslock
我最近和一些人一样,发现[ALAssetsLibrary enumerateGroupsWithTypes]喜欢在另一个线程上运行它的块.苹果公司没有证明这一点真可惜:-)
在我目前的情况下,我需要等待枚举完成,然后主线程返回任何结果.我显然需要某种线程同步.
我已经阅读了有关NSLock和NSConditionLock的内容,但似乎没有任何内容符合"发出此工作线程已完成的阻塞线程信号"的要求.这似乎是一个简单的需求 - 任何人都能指出我正确的方向吗?
你的线索和嘘声一如既往地受到欢迎,
M.
Geo*_*rge 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");
}
Run Code Online (Sandbox Code Playgroud)
我的输出是
main
main
main
Run Code Online (Sandbox Code Playgroud)
意味着在主线程中调用了块.这只是一个单独的事件.要解决您的问题,您只需要在到达最后一步时从块内以某种方式返回您的值.您可以告诉它是最后一步,因为对于组对象,将使用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)
}
}
Run Code Online (Sandbox Code Playgroud)
答案是使用 NSConditionLock 类......
typedef enum {
completed = 0,
running = 1
} threadState;
...
NSConditionLock *lock = [[NSConditionLock alloc] initWithCondition:running];
Run Code Online (Sandbox Code Playgroud)
然后关闭你的线程,或者在我的例子中调用 [ALAssetsLibrary enumerateGroupsWithTypes:]。然后用这个阻塞父线程......
// Await completion of the worker threads
[lock lockWhenCondition:completed];
[lock unlockWithCondition:completed];
Run Code Online (Sandbox Code Playgroud)
当子/工作线程中完成所有工作后,使用以下命令解除对父线程的阻塞...
// Signal the waiting thread
[lock lockWhenCondition:running];
[lock unlockWithCondition:completed];
Run Code Online (Sandbox Code Playgroud)