我有一个NSManagedObjectContext声明如下:
- (NSManagedObjectContext *) backgroundMOC {
if (backgroundMOC != nil) {
return backgroundMOC;
}
backgroundMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
return backgroundMOC;
}
Run Code Online (Sandbox Code Playgroud)
请注意,它使用专用队列并发类型声明,因此其任务应在后台线程上运行.我有以下代码:
-(void)testThreading
{
/* ok */
[self.backgroundMOC performBlock:^{
assert(![NSThread isMainThread]);
}];
/* CRASH */
[self.backgroundMOC performBlockAndWait:^{
assert(![NSThread isMainThread]);
}];
}
Run Code Online (Sandbox Code Playgroud)
为什么调用performBlockAndWait在主线程而不是后台线程上执行任务?
我正在使用Apple的并发核心数据调试器.
-com.apple.CoreData.ConcurrencyDebug 1
我不时得到__Multithreading_Violation_AllThatIsLeftToUsIsHonor__,即使我几乎可以肯定线程没有被违反.
这是发生异常的代码的一部分(代码是扩展NSManagedObject的协议的一部分):
public static func find(arrayBy predicate: NSPredicate, sort: [NSSortDescriptor] = [], limit: Int? = nil) -> [Self] {
let fetchRequest = NSFetchRequest<Self>(entityName: "\(Self.self)")
fetchRequest.predicate = predicate
fetchRequest.sortDescriptors = sort
do {
return try Context.current.fetch(fetchRequest) // Exception!!!
} catch let error {
Logger.fatal("Failed to perform fetch: \(error)")
return []
}
}
Run Code Online (Sandbox Code Playgroud)
代码在上下文perform:块中执行.
这是线程信息:
和debuger信息确认在右侧NSManagedContext上执行了执行:
(lldb) po Context.current
<StoreContext: 0x7f854b556610>
Run Code Online (Sandbox Code Playgroud)
实体名称已成功提取:
po fetchRequest.entityName!
"Position"
Run Code Online (Sandbox Code Playgroud)
谓词由纯String对象构成(根本不使用托管对象):
(lldb) po fetchRequest.predicate!
ANY employees.company.id == "282372"
Run Code Online (Sandbox Code Playgroud)
在这种情况下,根本不使用排序描述符:
po …Run Code Online (Sandbox Code Playgroud)