3

Say I have an instance variable MyObject that has been allocated and initialized. Then say I do this:

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

[self dismissModalViewController]; //this releases all instance variables, right?

So what happens is I have an NSManagedObjectContext called backgroundThread that does some work on an object in the background. This returns immediately and does the work in the background, and then dismissModalViewController is called, which deallocates all instance variables. So what if the modal view has now been dismissed, but the backgroundThread still needs to use the object? Is this an issue? What is the workaround?

And another thing: This MyObject is inserted into the managed object context backgroundThread. Does this mean that this NSManagedObjectContext will retain the object, even after dismissing the view?

I'm using ARC.

Snowman
  • 29,431
  • 43
  • 165
  • 290
  • If you mutex lock the thing, you wouldn't have to worry about it. – CodaFi Jun 30 '12 at 20:39
  • A mutex lock guarantees that while MyObject is being processed in the background, that no other thread can touch it, including deallocate it. – CodaFi Jun 30 '12 at 20:47
  • Does this prevent my view controller from being deallocated then? Or does it still deallocate normally, and when I remove the lock, the MyObject is freed? And how would I do a mutex lock? – Snowman Jun 30 '12 at 20:47
  • Unfortunately no. You'd have to use a retain like @MichaelDauterman says for that. And when you remove the lock, it would only be deallocated if it had a weak reference to its view controller. – CodaFi Jun 30 '12 at 20:50
  • To use a mutex lock, [check out this example](http://etutorials.org/Programming/Cocoa/Part+I+Introducing+Cocoa/Chapter+2.+Foundation/2.9+Threaded+Programming/). You could use the basic `NSLock`, or `NSRecursiveLock`, if there would be nested attempts to lock your code (which I don't see in the example you provided). **Note:** normally, when I use locking, I make my mutex lock (i.e. `NSLock` object) a instance variable of the class in which I use it, not a local variable. – Nate Jun 30 '12 at 21:03

2 Answers2

5

There are several things you need to think about here. First keep in mind that the block will capture whatever it refers to. So you might not need to do anything special and your code will work fine, depending on exactly what you are doing in your block. The rules for block capture are described in Apple's Block Programming Topics documentation and how each variable is treated depends on its type. In particular,

In a manually reference-counted environment, local variables used within the block are retained when the block is copied. Use of instance variables within the block will cause the object itself to be retained. If you wish to override this behavior for a particular object variable, you can mark it with the __block storage type modifier.

If you are using ARC, object variables are retained and released automatically as the block is copied and later released.

Another thing to consider is that access to the instance variables may or may not be thread safe. Accessing the instance variables through properties declared as atomic is a step in the right direction, but you may need to use mutex locks or other techniques to synchronize access depending on the specifics on the situation.

torrey.lyons
  • 5,359
  • 1
  • 19
  • 30
  • Note that atomic access is SLOW. – CodaFi Jun 30 '12 at 20:59
  • Declaring properties as `atomic` is actually very rarely a step in the right direction. Making a property `atomic`, by itself, does not make the variable thread-safe, under most concurrent access scenarios. You would still need to provide protection, for example, with a mutex lock. Once you provide the mutex lock, you generally don't need the property to be `atomic`, and as CodaFi said, it is slower. [Here's another discussion on this specific issue - atomic](http://stackoverflow.com/questions/588866/atomic-vs-nonatomic-properties) – Nate Jun 30 '12 at 21:16
  • Where can I find out more about the specifics of whether an instance variable is thread safe or not? I am using ARC.. – Snowman Jun 30 '12 at 21:31
  • At the risk of over simplifying a complicated topic, the main concern you'll have for thread safety is that another thread will modify the instance variables used in your block while it is running. If you know this won't happen from the logic of your application you can not worry about thread safety. If this is a concern you'll want to use some technique to synchronize access to your data from multiple threads such as discussed [here](https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html). – torrey.lyons Jun 30 '12 at 22:47
1

If you want to reference ivars or other properties of your (modal) view controller, you need to insure that the modal view controller still exists.

Here's a potentially useful hint from Apple's documentation on dismissModalViewControllerAnimated::

If you want to retain a reference to the receiver’s presented view controller, get the value in the modalViewController property before calling this method.

Another idea that might work would be to create & instantiate a separate object that encapsulates the data / objects you want to access from either the view controller, or any other thread.

Michael Dautermann
  • 86,557
  • 17
  • 155
  • 196
  • Wait I don't understand what you mean by your last point..who would own this separate object? – Snowman Jun 30 '12 at 20:41
  • I modified my answer with some other information I discovered (to use the "`modalViewController`" property of the view controller), but if you did go ahead and use a separate object, both the view controller and your background thread could have references to it (which should be okay within ARC or outside of ARC). – Michael Dautermann Jun 30 '12 at 20:44
  • Are you familiar with Core Data? Check out my edit..MyObject has been inserted into an NSManagedObjectContext..does this mean the context will retain the object even after the view has been dismissed? – Snowman Jun 30 '12 at 20:48
  • You haven't yet mentioned whether or not you're using ARC... if you are, you should be A-OK. I also like @torrey.lyons answer, +1 to him. – Michael Dautermann Jun 30 '12 at 20:59