0

I am initializing an object and then configuring it inline. But instead of the previous instance (if previously allocated) being deallocated before configuring it (on the directly following lines), the deallocation is being deferred. So all the configuring I do to it ends up being a deallocated object - which of course is not what I want.

For instance, if I run this code:

if paintingView != nil {
   paintingView.removeFromSuperview()
}

print("^^^^^^^^^^^^^ About to init")
paintingView = PaintingView(frame: TDTDeviceUtilites.screenFrame())

print("^^^^^^^^^^^^^ About to add view")
view.addSubview(paintingView)

print("^^^^^^^^^^^^^ About to configure")
self.configurePaintingView()

I will see the following messages in the Console:

^^^^^^^^^^^^^ About to init
^^^^^^^^^^^^^ About to add view
^^^^^^^^^^^^^ About to configure
***** Painting View Dealloc ***** //message from the dealloc method of the PaintingView class.

I would expect the dealloc to happen directly following the init line. What is going on? Note that this code is being called in NSOperationQueue().

How can I make sure the dealloc happens first, and why isn't that already the case?

Jeshua Lacock
  • 5,730
  • 1
  • 28
  • 58
  • You should write your code so you don't care when the old view is deallocated. How does `self.configurePaintingView` find the view to configure? Why don't you just pass `paintingView` as an argument, so it always uses the correct instance? – Kurt Revis May 07 '16 at 20:25
  • (Also, I'm having to read between the lines a lot -- this question is pretty confusing. A more complete example would help.) – Kurt Revis May 07 '16 at 20:25
  • I guess that is a good suggestion, but I am still baffled that the dealloc doesn't occur first and would like to understand why. – Jeshua Lacock May 07 '16 at 20:30
  • 1
    I'm assuming that `paintingView` is an instance variable, and previously held a difference instance of a `PaintingView`? Use Instruments with the Allocations tool (turning on "Record reference counts") to see what other retains, releases, and autoreleases happened to that instance. It's impossible for us to determine what they were, given only what you're providing here. – Kurt Revis May 07 '16 at 20:55
  • @DrBeardface Sorry should have shown that in my code - I am removing the view first if it isn't nil. – Jeshua Lacock May 07 '16 at 21:49
  • 1
    It's also possible something is autoreleasing that view. Try [adding an `autoreleasepool { }` block](http://stackoverflow.com/questions/24152050/what-is-the-equivalent-of-autoreleasepool-in-swift) around the code that removes the old view and sets the new one. But I'll reiterate that you _should not_ just sprinkle that in just to fix this problem -- it's incredibly fragile -- and that changing your code to be insensitive to the timing of `dealloc` is better. – Kurt Revis May 07 '16 at 21:53
  • @KurtRevis yes; it is an instance variable. If you care to write up your comments as an answer I would likely accept them as an answer. Thanks for your help. – Jeshua Lacock May 08 '16 at 01:55
  • @KurtRevis I don't understand why passing the new instance to my configure method would be any different than using the instance variable (both would have the same memory address). – Jeshua Lacock May 08 '16 at 03:33
  • You're right, it wouldn't. When I wrote that comment, it wasn't clear to me that `paintingView` was actually an instance variable, since you didn't show the code that declared it. – Kurt Revis May 08 '16 at 03:37
  • @KurtRevis well - I guess this has been a red herring for me. I added the memory address to the print lines, and it is indeed the old address that has been deallocated. Guess I should delete this post? – Jeshua Lacock May 08 '16 at 05:32

1 Answers1

0

Apple does things behind your back to make all apps more efficient. Sometimes what actually happens is surprising. However, it's always things that shouldn't really affect you.

One possible optimisation (and I haven't checked personally whether Apple does this or not) is deallocating things on a background thread. An object gets deallocated when its reference count goes down to zero. When that happens, it is marked as "this object will be deallocated", and it will be deallocated. But not necessarily in the thread that set the reference count to 0. Doing the actual dealloc on a separate thread makes better use of multiple processors and makes your foreground app run faster.

It shouldn't make any difference to your code.

gnasher729
  • 51,477
  • 5
  • 75
  • 98