self is saved because
self.image.hidden = YES;
actually
[[self image] setHidden:YES];
The image is not saved / cannot be saved directly, because it is not available until the block is executed, and [self image] is called to obtain the image.
The second example also preserves itself, although for a different reason. In Objective-C, when you access an instance variable directly, it is actually accessed through its own underlying structure. So, _image is actually self->_image after compilation. Again, the block needs access to itself, so it saves itself.
It is also worth noting that in any case, if the _image value is changed before the block is executed, the block will "see" the new value. This is often, but not always, what you want.
You have two options to avoid saving yourself. The first one will do this and fix the _image value at the moment the block is defined, so even if it changes, the block will see the original value. This approach is to define a local variable, set it to the current value returned by self.image , and then use this in a block:
UIImage *image = self.image; self.finishBlock = ^{ image.hidden = YES; }
Another approach is to commit a weak version of self and use it in a block. In this case, the block will have a weak - instead of a strong - link to itself (i.e., it will not save itself). However, the -image accessor on self method will still be called, so if the image is changed before the block starts, the new value will be used:
__weak YourClass *weakSelf = self; self.finishBlock = ^{ weakSelf.image.hidden = YES; }
Note that in this case, if self freed before the block is started, weakSelf will be zero, and the statement in the block will effectively be NOOP (message sends to nil to do nothing in Objective-C).