Ios 将引用传递给NSManagedObject';将属性设置为背景线程

Ios 将引用传递给NSManagedObject';将属性设置为背景线程,ios,core-data,thread-safety,nsmanagedobject,nsmanagedobjectcontext,Ios,Core Data,Thread Safety,Nsmanagedobject,Nsmanagedobjectcontext,我想做的是: Product *product = [fetchResult lastObject]; NSString *productID = product.atProductID; dispatch_async(queue, ^(void){ // Something with productID like NSLog(@"productID is %@", productID); }); 这样做安全吗?还是我需要为我的第二个队列创建另一个上下文,通过其内部ID获取产品,然后处理其

我想做的是:

Product *product = [fetchResult lastObject];

NSString *productID = product.atProductID;

dispatch_async(queue, ^(void){
// Something with productID like
NSLog(@"productID is %@", productID);
});
这样做安全吗?还是我需要为我的第二个队列创建另一个上下文,通过其内部ID获取产品,然后处理其atProductID属性

更新: 嗯,它揭示了这实际上是不安全的。一个简单的解决方案是复制productID字符串:

Product *product = [fetchResult lastObject];

NSString *productID = [product.atProductID copy];

dispatch_async(queue, ^(void){
// Something with productID like
NSLog(@"productID is %@", productID);
});

这将是安全的,因为您不会在后台线程中保留对上下文或其派生的任何引用。原因是上下文缓存它从持久存储中获取的数据,并且它自己管理该缓存。无论您是否保留指向该缓存的指针,它都可能会更改或销毁它,除非它用于上下文的线程。

以前没有使用过dispatch\u async,但我觉得这段代码一点也不健康

您正在使用在一个线程中创建的变量,并将其直接传递到另一个代码块中。正确的方法是将对象/参数传递给方法

需要注意的是,你的问题并不是100%准确。当你执行

NSString *productID = product.atProductID;

您正在创建一个与NSManagedObject(即产品)没有关联的全新NSString对象。因此,您的问题相当于为dispatch_async传递参数,与NSManagedObjects没有太大关系。您的代码看起来很好。如果要创建,则只需要一个单独的托管对象上下文 对其执行一些操作,例如长取或更改托管对象


此外,您可以毫无问题地使用
async
块范围内的变量。这就是CGD的最大优势。这些线程包含内存,因此我希望复制字符串。您可以通过记录指针地址进行检查

你没有去,但你回答了我的问题问题是,当我访问与NSManagedObject属性相关的属性时,它是否真的创建了NSString的新实例,或者它只提供对它的引用,因为这是Cocoa中的常见行为。如果可以,请提供一个链接,其中说明NSManagedObject属性访问器执行复制。很高兴我这样做了:)作为将来的参考,您可以通过将产品ID分配给其他对象(在NSString初始化之后)并记录这两个变量(NSString对象和属性)来进行快速检查要查看它们是否有相同或不同的值,不需要在相同的上下文中将变量传递给GCD。嗯,恐怕你错了,它只返回对保留字符串的引用。我想只要相应的NSManagedObject子类的属性中有一个“retain”修饰符,它就会继续这样做。这里有一些关于它的信息:。所以我在上面的例子中所做的是容易出错的。有趣的是,我没有意识到这一点,谢谢。你可以试试NSMutableString,但不确定,但可能有效不,我检查过了:GCD不会复制块内使用的变量,它只是保留一个指向它们的强指针,以确保它们不会在块完成执行之前被释放。好的,欢迎使用SOF。您需要勾选上面的复选标记。;-)