我在NSManagedObjectContext中添加了一个方法-dct_asynchronousTaskWithWorkBlock:completionBlock:
,它在另一个GCD队列中运行工作块,然后在主线程上运行完成块。该方法执行以下操作:
可以在GitHub上看到此添加内容。
我的问题是我在工作区中创建了一个新的User
托管对象,我想在完成块中引用它。我认为解决方案是创建对象ID的引用,如下所示:
__block NSManagedObjectID *objectID = nil;
[self.managedObjectContext dct_asynchronousTaskWithWorkBlock:^(NSManagedObjectContext *moc) {
NSManagedObject *user = // create new user.
objectID = [user objectID];
} completionBlock:^(NSManagedObjectContext *moc) {
NSManagedObject *user = [moc objectWithID:objectID];
}];
我也尝试过复制块,在这两种情况下,我在完成块中的objectID上得到了一个EXC_BAD_ACCESS。
是否可以从完成块引用工作块中的用户objectID?或者我是否需要处理在类别方法中传递引用的方法。
更新
Luke对于保留整个块调用是正确的,因为第一个用户位于后台线程中,而第二个用户位于主要位置。
这是我目前的解决方法:
__block NSManagedObjectID *objectID = nil;
[self.managedObjectContext dct_asynchronousTaskWithWorkBlock:^(NSManagedObjectContext *moc) {
NSManagedObject *user = // create new user.
objectID = [user objectID];
[objectID retain];
} completionBlock:^(NSManagedObjectContext *moc) {
NSManagedObject *user = [moc objectWithID:objectID];
[objectID release];
}];
我现在想知道这看起来是否奇怪。在阅读此代码后,您可能会询问是否存在泄漏。我知道该类别肯定会调用完成块,无论第一个块中发生了什么,但我不知道它是否只是从这段代码看起来很明显。
答案 0 :(得分:2)
卢克是对的,但是......
为什么要有工作区和完成区?
GCD API最初看起来像:
dispatch_async(q, workBlock, completionBlock);
但事实证明这很愚蠢。 workBlock总是知道它何时完成,为什么不将完成逻辑放入workBlock?除了制作更简单的API之外,它还消除了将状态从工作块传输到完成块的任何空间机制的需要。
dispatch_async(q, ^{
... do heavy duty work on background here ...
dispatch_async(mainQueue, ^{
... merge into main queue context here ...
... update UI ...
});
});
答案 1 :(得分:1)
如果您的类别的目的是保持您的工作和完成块清除与第二个MOC的设置和拆卸相关的任何代码,您可以从工作块返回完成块:
[self.managedObjectContext dct_asynchronousTask:^(NSManagedObjectContext *moc) {
NSManagedObject *backgroundThreadUser = // create new user.
NSManagedObjectID *objectID = [backgroundThreadUser objectID];
return ^(NSManagedObjectContext *moc) {
NSManagedObject *mainThreadUser = [moc objectWithID:objectID];
// ...
};
}];