3

I have this code in my app:

var newImage = // ...

if (imageView.Image != null && imageView.Image != newImage)
    imageView.Image.Dispose ();

imageView.Image = newImage;

I have three related questions:

  • Does it immediately release the memory occupied by the previous imageView.Image?
  • If it does, is there a cleaner solution?
  • Does this have anything to do with NSAutoreleasePool?
Dan Abramov
  • 264,556
  • 84
  • 409
  • 511

1 Answers1

6

Does it immediately release the memory occupied by the previous imageView.Image?

Not immediately but it should be much faster than waiting for the Garbage Collector.

Calling Dispose will drop the managed reference to the native UIImage. If nothing else (natively) has a reference to the UIImage (RetainCount == 0) then it will be freed (ObjC reference counting).

In your code imageView still has a reference to it until its Image property is set to newImage - which is why I answered not immediately.

If it does, is there a cleaner solution?

Not really. Letting the GC do it's work is cleaner looking - but image can be very big and are worth freeing asap.

Also it's not really worth (and would not be cleaner anyway) adding a local variable to make sure (if no other native reference exists) the image will be freed immediately - it will happen on the next line.

Does this have anything to do with NSAutoreleasePool?

Anything ? well it's memory related in both cases.

Creating images will use (cache) the current NSAutoreleasePool and will, eventually, be drained. If you process a lot of stuff (e.g. a loop) then it's often worth having your own, short-lived, pool to ensure a faster drain.

Some API (well know to require a lot of memory) are decorated with an attribute that will automatically add (btouch) an NSAutoreleasePool - but it's not easy to find out which.

In doubt you better use Apple Instruments to measure...

poupou
  • 43,413
  • 6
  • 77
  • 174
  • Thanks for the quick response, this is more or less what I expected. Regarding `NSAutoreleasePool`, I was hoping that maybe if I wrap assignment in a dedicated pool, I wouldn't have to write this `if` condition. I guess this isn't the case? I'm afraid I don't understand how `NSAutoreleasePool` should be used in MonoTouch, what draining is, and how it plays with Mono's GC. – Dan Abramov Apr 24 '13 at 22:50
  • 2
    `NSAutoreleasePool` is like ObjC (Apple documentation applies) and it's **not** directly related to the GC (which only cover managed references) since it's a **native** reference will be kept in the pool. That also means it does not *solve* using the `if` and calling `Dispose`. See Rolf's answer http://stackoverflow.com/a/10440506/220643 for an example where it *was* needed but any, previously, existing `UIImage` assigned to the `UIImageView.Image` won't be disposed (in that example) until the GC process it (so it would be better to call `Dispose` on it, if not null, like your own example). – poupou Apr 24 '13 at 23:02