Iphone 从后台线程访问实例变量

Iphone 从后台线程访问实例变量,iphone,objective-c,ios,multithreading,Iphone,Objective C,Ios,Multithreading,假设我有一个已分配并初始化的实例变量MyObject。然后说我这样做: [backgroundThread performBlock:^{ //do something with MyObject that might take some time }]; [self dismissModalViewController]; //this releases all instance variables, right? 因此,我有一个名为backgroundThread的NSManag

假设我有一个已分配并初始化的实例变量MyObject。然后说我这样做:

[backgroundThread performBlock:^{
    //do something with MyObject that might take some time
}];

[self dismissModalViewController]; //this releases all instance variables, right?
因此,我有一个名为
backgroundThread
NSManagedObjectContext
,它在后台对一个对象执行一些操作。这将立即返回并在后台执行工作,然后调用
dismissModalViewController
,它将释放所有实例变量。那么,如果模态视图现在已被取消,但
backgroundThread
仍需要使用该对象,该怎么办?这是一个问题吗?解决办法是什么

还有一件事:这个MyObject被插入到托管对象上下文后台线程中。这是否意味着此NSManagedObjectContext将保留对象,即使在取消视图之后也是如此


我正在使用ARC。

如果要引用IVAR或(模态)视图控制器的其他属性,需要确保模态视图控制器仍然存在

以下是一个潜在的有用提示:

如果要保留对接收器显示视图的引用 控制器,获取之前modalViewController属性中的值 调用此方法


另一个可行的想法是创建并实例化一个单独的对象,该对象封装了要从视图控制器或任何其他线程访问的数据/对象

这里有几件事你需要考虑一下。首先请记住,块将捕获它所引用的任何内容。因此,您可能不需要做任何特殊的事情,您的代码也可以正常工作,具体取决于您在块中所做的事情。块捕获的规则在苹果的文档中有描述,每个变量的处理方式取决于它的类型。特别是,

在手动引用计数的环境中,复制块时会保留块内使用的局部变量。在块中使用实例变量将导致保留对象本身。如果希望覆盖特定对象变量的此行为,可以使用_块存储类型修改器对其进行标记

如果使用的是ARC,则对象变量将在复制块并随后释放时自动保留和释放


另一个要考虑的是,对实例变量的访问可能是线程安全的,也可能不是线程安全的。通过声明为

原子的属性访问实例变量是朝着正确方向迈出的一步,但根据具体情况,您可能需要使用互斥锁或其他技术来同步访问。

如果您使用互斥锁,你不必担心。互斥锁可以保证当MyObject在后台处理时,没有其他线程可以接触它,包括解除分配它。这会阻止我的视图控制器被解除分配吗?或者它仍然正常解除分配,当我移除锁时,MyObject被释放?我该怎么做互斥锁呢?不幸的是没有。你必须像@MichaelDauterman说的那样使用retain。当您移除锁时,只有当它对其视图控制器具有弱引用时,才会解除分配该锁。如果有嵌套尝试锁定代码(我在您提供的示例中没有看到),则可以使用基本的
NSLock
,或
NSRecursiveLock
。注意:通常,当我使用锁定时,我会将我的互斥锁(即
NSLock
对象)作为我使用它的类的实例变量,而不是局部变量。等等,我不明白你最后一点的意思。谁会拥有这个单独的对象?我用我发现的一些其他信息修改了我的答案(使用“
modalViewController
”属性),但如果继续使用单独的对象,则视图控制器和后台线程都可以引用它(在ARC内或ARC外都可以).你熟悉核心数据吗?请查看我的编辑..MyObject已插入到NSManagedObjectContext中..这是否意味着即使在视图被取消后,上下文仍将保留该对象?你还没有提到你是否正在使用ARC…如果是,你应该是A-OK。我还喜欢@torrey.lyon的答案,+1给他。注意原子访问速度很慢。将属性声明为
原子
实际上很少是朝着正确方向迈出的一步。在大多数并发访问场景下,仅使属性
原子
本身并不能使变量线程安全。您仍然需要提供保护,例如,使用互斥锁。一旦提供互斥锁,你通常不需要属性是原子的,就像CodaFi说的,它是慢的。我在哪里可以找到关于实例变量是否线程安全的更多细节呢?我使用的是ARC。冒着过度简化一个复杂主题的风险,你对线程安全的主要关注是另一个read将在块运行时修改块中使用的实例变量。如果从应用程序的逻辑中知道这不会发生,则不必担心线程安全。如果这是一个问题,则需要使用一些技术来同步从多个线程访问数据,如前所述。