I have looked at your actual code in "Update 2", but it's missing a lot of information. For example, is _aimageView
an instance variable? local variable? or what? And what causes this onSuccess
to be called?
If _aimageView
is a local variable then I don't see evidence of a retain cycle.
My first thought is I don't understand why you want to guarantee that the code inside the body of the block runs in this example. It looks like the code inside is just updating some UI elements. Well, if the UI is no longer displaying (as when the current object has no references to it other than perhaps by this block), what's the point of updating the UI elements?
It's important to know what causes onSuccess
to be called because different types of callbacks require different memory management architectures. For example, if the block is fired in response to a touch or some kind of event like that, then chances are that the object pointed to by self
(which is probably some kind of view or view controller) must be still alive in order that the event occurs. If that's the case, then __weak
will do what you want.
Basically, by the naming of these variables, it is reasonable to conclude that _aimageView
is probably an image view that is conceptually "owned" by the current object, and the onSuccess
is a completion block that is "owned" by the image view. Unless some other object has a strong reference to it, the "owned" object's lifetime is limited to its "owning" object's lifetime. Thus the block will not outlive the image view, which will not outlive the current object.
The only way that what you are afraid of (when the block runs, the object pointed to by self
is deallocated) can happen, is if some other object stores a strong reference to _aimageView
, or to the block. For the block, it's very unlikely that a "success block" of one object will be stored with other objects. For the image view, it's similarly unlikely if the image view "belongs" to the current object. (It's conceivable that it may be stored by the autorelease pool or something; but the autorelease pool will not call stuff on it except release, so that's not a problem.)
The only exception I can think of is if the image view is kept by a pending network operation or something, which when it is done calls the onSucess
block. But if that were the case, I would say it's bad design to have a single object serve as both a view and a network operation. Rather, in that case, one should have a dedicated network operation object, which is a local variable, and set a completion block on it (e.g. store image in image view, set labels, etc.), start the operation, and not need to store the operation. Then the block can refer to self
strongly, but there is no retain cycle.
To summarize, the block (and the image view that owns it) should fall into one of two categories, based on who keeps it alive (i.e. who retains it, who maintains a strong reference to it):
If self
keeps it alive: e.g. A view controller keeps its views and subviews alive. In this case, it is safe to use __weak
because the block does not exist outside of the life of self
.
If someone else keeps it alive: e.g. an alert view -- you just create it and show it; the system maintains it on screen afterwards. In this case, self
should not (and does not need to) have a reference to it, and it's okay to reference self
strongly in the block; it won't cause a retain cycle.
Try to avoid situations where both self
and someone else keep it alive.