gpt4 book ai didi

ios - 核心数据和 GCD : Passing the correct managed object context to custom NSManagedObjects

转载 作者:可可西里 更新时间:2023-11-01 17:09:16 25 4
gpt4 key购买 nike

我收到运行时错误,这似乎是由于我错误地执行了 GCD 而导致的结合我的自定义 NSManagedObjects。

嵌套在 GCD 中调用,我正在使用自定义 NSManagedObjects,它(似乎)有自己的托管对象上下文(= self.managedObjectContext)。

我正在使用 UIManagedDocument 提供的托管对象上下文在应用程序委托(delegate)中创建托管对象上下文: self.managedDocument.managedObjectContext .

我不明白如何将正确的托管对象上下文传递到我的自定义 NSManagedObjects。我需要如何更改我的代码才能使用正确的托管对象上下文?

这是我的主要方法(在​​ View Controller 中):

dispatch_queue_t queue;
queue = dispatch_queue_create("queue", NULL);
dispatch_async(queue, ^{
// ...
NSDecimalNumber *value = [reportedPeriod
valueForCoa:figure.code
convertedTo:self.currencySymbol];
// ...});
}

在这个主要方法中,我没有任何对托管对象上下文的引用,我只是调用 valueForCoa:convertedTo: (编码如下):

- (NSDecimalNumber*)valueForCoa:(NSString*)coaStr
convertedTo:(NSString*)targetCurrencyStr {
// ...
CoaMap *coa = [CoaMap coaItemForString:coaStr
inManagedObjectContext:self.managedObjectContext];
// ...
}

valueForCoa是我的自定义子类 NSManagedObject 中的一个方法 ReportedPeriod并使用其(默认)托管对象上下文 self.managedObjectContext .

应用通常会在自定义子类 NSManagedObject 中崩溃 CoaMap在执行获取请求时在以下方法中:

+ (CoaMap*)coaItemForString:(NSString*)coaStr 
inManagedObjectContext:(NSManagedObjectContext*)context {

NSFetchRequest *request = [NSFetchRequest
fetchRequestWithEntityName:NSStringFromClass([self class])];
NSPredicate *predicate =
[NSPredicate predicateWithFormat:@"coa == %@",coaStr];
request.predicate = predicate;
// ** The runtime error occurs in the following line **
NSArray *results = [context executeFetchRequest:request error:nil];
// ...
}

错误信息是:Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSCFSet: 0x9a8a4a0> was mutated while being enumerated.

能否请您帮我解决这个问题,并就如何改进我的代码以传递正确的托管对象上下文(或如何确保在所有方法中使用正确的上下文)提出一些建议?

非常感谢!

最佳答案

该错误通常与跨不同线程或队列错误地使用托管对象有关。您在主队列上创建了 MOC,但您在后台队列上使用它而没有考虑这一事实。在后台队列上使用 MOC 并没有错误,但您需要意识到这一点并做好准备。

您没有说明您是如何创建 MOC 的。我建议您应该这样做:

NSManagedObjectContext *context = [[NSManagedObjectContext alloc]
initWithConcurrencyType: NSMainQueueConcurrencyType];

通过主队列并发,您可以在主线程上正常使用它。但是,当您在调度队列中时,请执行以下操作:

[context performBlockAndWait:^{
NSFetchRequest *request = [NSFetchRequest
fetchRequestWithEntityName:NSStringFromClass([self class])];
NSPredicate *predicate =
[NSPredicate predicateWithFormat:@"coa == %@",coaStr];
request.predicate = predicate;
NSArray *results = [context executeFetchRequest:request error:nil];
// ...
}];

这将确保 MOC 的工作发生在主线程上,即使您在后台队列中也是如此。 (从技术上讲,它实际上意味着 MOC 在后台的工作将与其在主队列上所做的工作正确同步,但结果是一样的:这是执行此操作的安全方法)。

类似的方法是使用 NSPrivateQueueConcurrencyType 代替。如果这样做,您将在 MOC 的任何地方使用 performBlockperformBlockAndWait,而不仅仅是在后台线程上。

关于ios - 核心数据和 GCD : Passing the correct managed object context to custom NSManagedObjects,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14651259/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com