使用 Core Data 等待 withTaskGroup 有时会失败
Posted
技术标签:
【中文标题】使用 Core Data 等待 withTaskGroup 有时会失败【英文标题】:await withTaskGroup with Core Data sometimes fails 【发布时间】:2021-09-05 15:59:57 【问题描述】:我有以下任务组,使用 Swift 5.5 中的 async/await 并发,我在其中迭代米,从 Core Data 获取 onboardingMeter
。这在 5 次中有 4 次都可以正常工作,但随后会导致 ios 应用程序崩溃。我正在通过从 iOS 设备中删除应用程序来测试这一点,并从一开始就运行入职。有时我可以连续运行 4 次或 5 次或 6 次没有问题,然后它突然崩溃并出现以下错误:
2021-09-05 09:11:01.095537+0200 Curro[12328:1169419] [error] error: Serious application error. Exception was caught during Core Data change processing. This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification. -[__NSCFSet addObject:]: attempt to insert nil with userInfo (null)
CoreData: error: Serious application error. Exception was caught during Core Data change processing. This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification. -[__NSCFSet addObject:]: attempt to insert nil with userInfo (null)
2021-09-05 09:11:01.095954+0200 Curro[12328:1169419] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFSet addObject:]: attempt to insert nil'
*** First throw call stack:
(0x1857b105c 0x19dc63f64 0x1858ba538 0x1858c5df8 0x1857c68bc 0x18ce313d8 0x18cd13314 0x18cd140cc 0x105616700 0x105626a90 0x185769ce4 0x185723ebc 0x1857373c8 0x1a0edd38c 0x1880dae9c 0x187e58864 0x18d36da2c 0x18d29ab70 0x18d27bf2c 0x1048bba04 0x1048bbab0 0x10551da24)
libc++abi: terminating with uncaught exception of type NSException
这是失败的代码,let onboardingMeter = await OnboardingMeter.fromMeterDict
永远不会返回,失败时我看不到第二个打印语句。
这是 Swift 测试版中的一个错误,还是我在这里犯了任何错误?我会在新的 iOS 15 测试版到来,以及 iOS 15 的正式版本发布时再试一次。
await withTaskGroup(of: OnboardingMeter.self) group in
for (number, codableAddress) in meters
group.addTask
print("The following statement sometimes fails to return an onboarding meter, resulting in a crash")
let onboardingMeter = await OnboardingMeter.fromMeterDict(number, address: codableAddress, in: moc)
print("onboardingMeter:", onboardingMeter)
return onboardingMeter
for await meter in group
onboardingMeters.append(meter)
OnboardingMeter.fromMeterDict
函数:
extension OnboardingMeter
static func fromMeterDict(_ number: String, address: CodableAddress, in moc: NSManagedObjectContext) async -> OnboardingMeter
let me: OnboardingMeter = await moc.findOrCreateInstance(of: self, predicate: NSPredicate(format: "number == \(number)"))
let address = await Address.createOrUpdate(from: address, in: moc)
await moc.perform
me.address = address
me.number = number
return me
和 findOrCreateInstance:
func findOrCreateInstance<T: NSManagedObject>(of type: T.Type, predicate: NSPredicate?) async -> T
if let found = await self.findFirstInstance(of: type, predicate: predicate)
return found
else
return T(context: self)
【问题讨论】:
显示OnboardingMeter.fromMeterDict
。
听起来像一个核心数据线程错误。我建议向 Apple 提交报告。
【参考方案1】:
虽然我需要查看更多代码来确认这一点,但我相信您正在返回一个已注册到托管对象上下文的托管对象。只有在 perform
调用的闭包中引用此类注册对象才有效。如果您需要在不同的执行上下文之间引用托管对象,可以使用对象 ID 并根据需要重新获取,或者使用获取请求的字典表示选项:
let request: NSFetchRequest = ...
request.resultType = NSManagedObjectIDResultType // or NSDictionaryResultType
return request.execute()
强烈建议您观看this video from WWDC。在 10:39 的那一刻,他们正在谈论这个。
【讨论】:
以上是关于使用 Core Data 等待 withTaskGroup 有时会失败的主要内容,如果未能解决你的问题,请参考以下文章