在我的代码中,我需要观察NSBlockOperation已完成并通过 block 值进行通知。
我想在没有KVO,代表或子类的情况下这样做。为此,我使用了GCD和dispatch_group_notify。这段代码适合我,但我不确定内存管理。这种方法会导致崩溃吗?例如,一个潜在的问题可能是在dispatch_release(group)之后阻止调用;
- (void)collectLastRunnedDate: (void (^)()) block
{
NSAssert(block, @"Block should not be nil");
dispatch_group_t group = dispatch_group_create();
dispatch_group_notify(group, dispatch_get_main_queue(), block);
NSBlockOperation * blockOperation = [NSBlockOperation blockOperationWithBlock:^{
dispatch_group_enter(group);
self.lastRunnedDate = [self lastRunnedDateForPeriodicName:@"daily"];
if(!self.lastRunnedDate)
{
self.lastRunnedDate = [self lastRunnedDateForPeriodicName:@"weekly"];
}
if(!self.lastRunnedDate)
{
self.lastRunnedDate = [self lastRunnedDateForPeriodicName:@"monthly"];
}
if(!self.lastRunnedDate)
{
self.lastRunnedDate = [[Preferences sharedInstance] periodicsLastRunned];
}
dispatch_group_leave(group);
dispatch_release(group);
}];
[[NSOperationQueue queue] addOperation:blockOperation];
}
答案 0 :(得分:0)
来自dispatch_release
的{{3}}:
组 - 观察派遣小组。系统保留该组,直到该块运行完成。
注意:如果您使用ARC,则无需拨打{{1}}。
HTH
答案 1 :(得分:0)
您正在错误地使用该群组。
在输入任何内容之前,您正在呼叫dispatch_group_notify()
。来自文档:
如果组为空(没有块对象与调度组关联),则立即提交通知块对象。
这适用于您如何使用它。
与上述相关的是您使用与其相同的代码输入块。那不是正常模式。您通常在提交之前调用dispatch_group_enter()
将调用dispatch_group_leave()
的异步任务,以便该组在同步代码中具有正数。
所以,你可以这样做:
- (void)collectLastRunnedDate: (void (^)()) block
{
NSAssert(block, @"Block should not be nil");
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
NSBlockOperation * blockOperation = [NSBlockOperation blockOperationWithBlock:^{
// whatever work the block should do goes here
dispatch_group_leave(group);
}];
[[NSOperationQueue queue] addOperation:blockOperation];
dispatch_group_notify(group, dispatch_get_main_queue(), block);
dispatch_release(group); // Only needed if you're not using ARC
}
由于您似乎只是将操作对象提交到匿名操作队列,因此您可以轻松使用dispatch_group_async()
。这有效地为您进入和离开操作。
此外,如果您不知道,NSOperation
具有completionBlock
属性,该属性是在操作完成时自动运行的块。当然,NSBlockOperation
继承了这一点。您可以将其设置为一个块,它将您的block
参数异步提交到主队列,并完全避免使用调度组:
- (void)collectLastRunnedDate: (void (^)()) block
{
NSAssert(block, @"Block should not be nil");
NSBlockOperation * blockOperation = [NSBlockOperation blockOperationWithBlock:^{
// whatever work the block should do goes here
}];
blockOperation.completionBlock = ^{
dispatch_async(dispatch_get_main_queue(), block);
};
[[NSOperationQueue queue] addOperation:blockOperation];
}