Object lifecycle with a method receiving a block, under ARC - ios

Right now I have something like this:
- (void)viewDidLoad
{
MyObject *myObject = nil;
#autoreleasepool
{
myObject = [[MyObject alloc] init];
[myObject doSomethingWithBlock:^{
NSLog(#"Something Happened");
}];
}
NSLog(#"End of method");
}
And the doSomethingWithBlock: has the following:
- (void)doSomethingWithBlock:(void(^)())aBlock
{
[self performSelector:#selector(something:) withObject:aBlock afterDelay:4.0f];
}
And the something:
- (void)something:(void(^)())aBlock {
aBlock();
}
I understand that the block is being passed between stacks frames, so it's kept alive until it actually is executed and it is disposed. But why when the "End of method" is called does myObjct still exists? I know that I am not referencing the object from within the block, so shouldn't it be released within the autorelease pool? Or is this a compiler detail (if it should actually release it there, or after the method returns), and I shouldn't care about it?
Someone pointed out that performSelector will retain the target so I used this instead:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 4 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
aBlock();
});

It is not clear to me whether the question is about the lifetime of the block, as per the title, or the lifetime of the object referenced by myObject, so we'll cover both.
First, the stack allocation of blocks in an optimisation and something programmers should not really need to be aware of. Unfortunately when blocks were first introduced the compiler was not smart enough to handle this optimisation completely automatically, hence the need to know about Block_copy() etc. But the compiler is now much smarter and the programmer can pretty much forget about stack allocation of blocks.
This answer applies to Xcode 5.0.2/Clang 4.2. Use a different (earlier) version and YMMV.
Second, the block:
^{ NSLog(#"Something Happened"); }
is not actually stack allocated at all. As it references no values from the environment it is statically allocated and never needs to be placed on the stack or moved to the heap - another optimisation. To get a stack allocated block just change it to:
^{ NSLog(#"Something Happened: %p", self); }
which will be stack allocated (and don't worry about possible retain cycles, that's another topic...)
With that out of the way, let's look at the lifetimes:
The object:
The variable myObject has a lifetime of at most the call to viewDidLoad, the variable is created on entry to the method and destroyed on exit, if precise lifetime semantics are in force, or earlier if not needed and precise lifetime semantics are not in force - the latter is the default allowing the compiler to optimise storage use (independent of ARC). By default local variables have a strong ownership qualifier, so an ownership interest is asserted for any reference stored in one. ARC will release that ownership interest when another reference is stored in the variable or when the variable itself is destroyed. The latter will happen in this case and the variable is destroyed at some time after the last use of it and the end of the method - depending on how the compiler does its optimisations.
All this means that the object referenced by myObject may or may not be still around at your call to NSLog(). In the case of using performSelector:withObject:afterDelay: that call will assert ownership over the object until after the selector has been executed -= so the object will live. In the case of using dispatch_after the object is not required and so will not stay alive.
The block:
As mentioned above as written the block is statically allocated so lifetime is easy - it always exists. More interesting is modifying it as above to make it stack allocated.
If the block is stack allocated it will exist in the stack frame of the viewDidLoad call and unless moved or copied to the heap it will disappear when that call returns.
The call to doSomethingWithBlock: will be passed a reference to this stack allocated block. This is possible as doSomethingWithBlock: expects a block and code within it can move it to the heap if needed as it knows it is a block.
Now it gets interesting. Within doSomethingWithBlock: in the performSelector:withObject:afterDelay: case the block is passed as the withObject: parameter which is of type id - which means the called code expects a standard Objective-C object and those live on the heap. This is a case of type information loss, the caller has a block, the callee only sees an id. So at this point the compiler inserts code to copy the block to the heap and passes that new heap block to performSelector:withObject:afterDelay: - which treats it as it would any other object. [Older compilers did not always do this, the programmer had to know that type information loss was about to occur and manually insert code to move the block to the heap.]
In the case of dispatch_after, the function argument is block typed so the compiler just passes a stack allocated block on. However the dispatch_after function copies the block to the heap, as per its documentation, and there is no problem.
So in either case a stack allocated block is copied to the heap before viewDidLoad finishes and its stack frame is destroyed taking with it the stack allocated block.
HTH.

It is declared outside of the autorelease pool, so it should exist after it. It's all about scope where the object is declared, not allocated. By your logic class variables allocated inside an autorelease pool should be nil'd at the end of the pool and not usable elsewhere.
Example
-(void)function
{
MyObject *object; //MyObject declared here
if(someBoolean)
{
object = [[MyObject alloc] init]; //MyObject allocated here
}
//This is outside the scope of allocation,
//but it's still inside the scope of declaration.
//If ARC referenced the scope of allocation your
//object would not be valid here, as ARC would
//release it as out of scope.
}

Related

What is the correct way to be sure that the object will be there and it won't leak while using blocks with ARC on iOS?

Which of the following code section is correct?
Definition of correct for "me":
It should not have a retain cycle and so should not leak.
It must guarantee the running of method2 and method3. So MyObject variable in block must never ever be nil.(which may occur in __weak definitions...) (I do not want to check if it is nil to prevent crash. I always want it to be non-nil)
Update: (Additional Info)
Instruments tool did show strange leaks until I replace __block with __weak. However, after that I remembered that __weak references may disappear anytime. I have to be sure that it doesn't disappear and leak too. I don't have a timer. This someMethod is called on main thread when it observes a specific NSNotification.
#implementation MyObject...
-(void)someMethod{
AnotherObject *abc=[[AnotherObject alloc]init];
__weak MyObject *weakSelf=self;
abc.onSuccess=^{
__strong MyObject * strongSelf = weakSelf;
[strongSelf method2];
[strongSelf method3];
}
}
OR
#implementation MyObject...
-(void)someMethod{
AnotherObject *abc=[[AnotherObject alloc]init];
__block MyObject *blockSelf=self;
abc.onSuccess=^{
[blockSelf method2];
[blockSelf method3];
blockSelf=nil;
}
}
Update 2: Actual Code which always leaks if I don't use __weak:
__block RButton *_self=self;
_aimageView.onSuccess=^(void){
[_self.headerLabel setText:[_self.book title]];
_self = nil;
};
A block can mention self without causing any leak. So the first thing to do is specify the circumstances. Why do you think your block leaks? Have you checked? There's no point worrying if there is no reason to worry.
If the block's mentioning self does cause a leak, then the steps you can take depend upon the reason why that is happening. But you haven't shown us that. For example, a dispatch timer block that mentions self might cause a retain cycle, but when you are done with the timer you can break the cycle, so then there's no leak.
Thus it is better to understand a particular retain cycle than to program every block defensively when you don't have to.
EDIT (in response to your comment) This code from my book demonstrates various ways of handling memory management in an NSNotification observer situation: click here
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.
As you require to guarantee that method2 and method3 are executed then you have a requirement that the object referenced by self stays alive. To do this you follow the standard pattern: keep a strong reference for as long as you need it. Your second code fragment does that.
Reference cycles are not inherently bad, it is unmanaged ones that are. Here you make a cycle and then break it, so there is no issue.
(Note as you can send a message to nil the first code fragment will not crash if strongSelf is nil - it just won't do anything.)
-(void)someMethod{
AnotherObject *abc=[[AnotherObject alloc]init];
abc.onSuccess=^{
[self method2];
[self method3];
}
}
This will make. It won't cause a retain cycle.

Memory issue when calling dispatch_async with local variable

I am having issues in code when calling dispatch_async. I think that issue is due to ARC reclaiming the object, before it is used in a block, as the method that dispatches it finishes.
- (void) method:(SomeClass *) someClass {
// local variable
NSNumber *someValue = someClass.somePropertyOnManagedObject;
dispatch_async(queue, ^() {
/* call some singleton object passing variable
* when access the variable, reference is nil
*/
[[DashboardFacade sharedInstance] someMethod:someValue];
});
}
After having looking through much documentation, I conclude
Block accesses no parameters – nothing to discuss
Block accesses simple type parameters e.g. BOOL, int - these are copied and not a problem
Block accesses parameter of method that dispatched it - I am not sure, but think
that this is ok
Block accesses property of self – as long as self “lives” until the call has finished ok
Block accesses local variable in method that dispatched it
If we use some semaphores such that we wait for the block to return before leaving the method, then all ok
Otherwise variable may have been garbage collected before block can use.
I think that the solution is to use __block modifier such that ARC retains the variable.
My question is
Is the above technically correct, e.g. using __block will resolve the problem and not introduce other problems?
Why can't I find this anywhere on the internet/google?
Is the above technically correct, e.g. using __block will resolve the
problem and not introduce other problems?
Yes it's technically correct, __block, on ARC, allows you to change the variable (in this case to where its pointing, since it's a NSNumber *), that was declared outside the block context.
Why can't I find this anywhere on the internet/google?
I think the problem is not related to this particular place of your code, but something else.
someValue inside the block can be nil only if it is nil after this assignment:
NSNumber *someValue = someClass.somePropertyOnManagedObject;
Blocks retain objects that are being captured by the blocks as a result of those variables being used inside the blocks. And it doesn’t matter if it is self or a local variable from the scope that is visible to the block.

Confusion about ARC , AutoRelease

I am new to IOS development and I have started to learn objective c to program towards IOS 7. and as I know, it is way easier to code now than it has been before because of the Automatic reference counting.
there are a couple of things I do not understand . in MAIN method we have the autoreleasepool block, so my first question is that in order to enable ARC , the code has to be inside this block? if no, then what is the difference between the code that is inside autoreleasepool and the rest those aren't?
my second question is that when I am writing my IPHONE programs , I have bunch of classes and non of those codes are inside "autoreleasepool" , only the code inside the MAIN method.
int main(int argc, char * argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil,
NSStringFromClass([HomepwnerAppDelegate class]));
}
}
so , does this mean that this block somehow magically gets applied to all lines of code inside any other classes of the same program?
My last question is that whether with ARC or without it, if we had a declared pointer variable inside a method, does the object gets released/destroyed when the method returns/exit?
assume we have a method like this :
- (void)doSomething {
NSMutableArray *allItems = [[NSMutableArray alloc] init];
NSString *myString = #"sample string";
[allItems addObject:myString]
}
then when we call this method and it exits, what would happen to those local variables defined inside the method ? is there any difference in the outcome if we are using ARC or not ? (Object are still in the memory or not)
Autorelease pools predate ARC by about 15 years. Cocoa uses a reference-counting memory management scheme, where (conceptually, at least) objects are created with a reference count of 1, retain increases it by 1 and release decreases the count by 1, and the object is destroyed when the count gets to 0.
A problem with this scheme is that it makes returning an object kind of awkward, because you can't release the object before you return it — if you did, it might be destroyed before the other method got to use it — but you don't want to require the other method to release the object either. This is where autorelease pools come in. An autorelease pool lets you hand an object to it, and it promises to release the object for you later. Under manual retain/release (the way we used to do things before ARC), you did this by sending autorelease to an object.
OK, so then ARC comes into the picture. The only thing that really changes with ARC is that you aren't the one writing retain, release and autorelease anymore — the compiler inserts them for you. But you still need an autorelease pool for autoreleased object to go into.
As for your second question:
My last question is that whether with ARC or without it, if we had a declared pointer variable inside a method, does the object gets released/destroyed when the method returns/exit?
assume we have a method like this :
- (void)doSomething {
NSMutableArray *allItems = [[NSMutableArray alloc] init];
NSString *myString = #"sample string";
[allItems addObject:myString]
}
then when we call this method and it exits, what would happen to those local variables defined inside the method ? is there any difference in the outcome if we are using ARC or not ?
If you're using ARC, the compiler will release any objects referenced by local variables. If you're not using ARC, you'd need write [allItems release] yourself, because the variable going out of scope does not magically cause the object it references to be released.
new to IOS development
Best not to worry, Automatic means that you mostly concentrate on other things ^)
does this mean that this block somehow magically gets applied to all lines of code inside any other classes of the same program
Yes. You're in main function, so all the code that is executed has to be inside this function - your app will terminate once it ends. Unless you create a separate thread, but it's hard to do that by accident.
the code has to be inside this block
As said above, all of your code on main thread will execute within this block.
what would happen to those local variables defined inside the method
You're guaranteed that they will be destroyed before returning.
in MAIN method we have the autoreleasepool block, so my first question is that in order to enable ARC, the code has to be inside this block? if no, then what is the difference between the code that is inside autoreleasepool and the rest those aren't?
ARC is enabled by corresponding Objective-C compiler setting. If you create a new project in the latest version of Xcode it will be enabled by default.
The #autorelease keyword places code inside the curly brackets into autorelease pool scope. Autorelease pools are used both with ARC and manual memory management.
my second question is that when I am writing my IPHONE programs , I have bunch of classes and non of those codes are inside "autoreleasepool" , only the code inside the MAIN method.
iOS applications are event based. Main thread starts event loop when you call UIApplicationMain function processing touch events, notifications etc. This event loop has its own autorelease pool that autoreleases objects at the end of the loop iteration. This autorelease pool has nothing to do with the autorelease pool you see in main function.
My last question is that whether with ARC or without it, if we had a declared pointer variable inside a method, does the object gets released/destroyed when the method returns/exit?
If you use ARC the objects will be released (unless you return a reference to an object from the method). In MMR you would need to manually send release message to destroy the objects.

Keeping a strong pointer to a local object

I encountered this thing in a book which I am reading and it got me thinking:
"When you allocate a block, it is created on the stack. This means that, even if you were to keep a strong reference to it, calling it later would result in a crash because the memory would be destroyed as soon as you leave the method in which it was defined."
I thought if I have a strong pointer to something, it is kept alive?
Does this mean this does not apply for objects allocated on the stack?
I am trying to think of an example without using blocks...(e.g., of pointer - maybe an ivar- pointing to a stack allocated object which gets destroyed even though the pointer is alive)
Objects are never allocated on the stack in Objective-C. Blocks are special however, since they are stack allocated. So if you want to retain a pointer to a block, you must first copy it by using Block_copy and use the copy, then release it with Block_release. This must be done if the block is to be used after the scope it was declared in is destroyed. More on the matter here: https://developer.apple.com/library/mac/documentation/cocoa/Conceptual/Blocks/Articles/bxUsing.html (under "Copying Blocks"). Yet again though, this does not apply to regular objects.
Blocks can be messaged like objects. To move them from the stack to the heap, just "copy" them.
void (^stackBlock)() = [^(){
NSLog(#"Hello world");
} copy];

How long does an autoreleased static object declared globally, survive in memory?

If I declare a static object handle in a class file in global scope. And the object assigned to this handle is an autoreleased one. Then for how long will this object remain in memory during my application life cycle ?
If I declare a static object handle in a class file in global scope. And the object assigned to this handle is an autoreleased one. Then for how long will this object remain in memory during my application life cycle?
Short Answer: You want your global to be a strong reference. In MRC, you must add the retains and releases for globals. In ARC, the global is implicitly strong (and ARC adds them for you).
Long Answer:
Under ARC, your static global variable is a strong reference. In MRC, you would retain such a variable when set and then release the previous object. If you did not, then you could still access it after it were deallocated (dangling pointer).
Because it is a strong reference, your object will remain valid until a) the strong reference by the global variable is given up and b) the autorelease pool is drained c) and of course any other strong references are given up.
So if you are using strong references for that global and you never reassign it (logically, giving up the global's strong reference), then your object would never be dealloc'ed.
When you use unsafe nonretained semantics (by decoration in ARC, or the default for a static in MRC), the object would be -dealloced when the current autorelease pool is drained and all strong references are removed. This is easiest to illustrate with a program (MRC);
static MONObject * GlobalObject;
//
// In MRC, you must add the reference counting to ensure you do not end up with a dangling
// pointer, so false is what how your program should be written in MRC.
//
// In ARC, your program will look like NonRetainedOwnership because it treats the global
// as a strong reference.
static const bool NonRetainedOwnership = ...T/F...;
...
// assume GlobalObject is accessed from one thread only -- i won't bother with
// the supporting code to illustrate how this should be made thread safe.
- (MONObject *)sharedObject
{
if (nil == GlobalObject) {
if (NonRetainedOwnership) {
// don't do this! lifetime will be determined by strong client references
// and the reference you rely on now will be lost when the thread's current
// autorelease pool is drained -- leaving you with a dangling pointer which
// will cause issues when -sharedObject is called again.
GlobalObject = [[MONObject new] autorelease];
}
else {
// Good - keep a strong reference:
GlobalObject = [MONObject new];
}
}
return GlobalObject;
}
- (void)disposeSharedObject
{
if (NonRetainedOwnership) {
GlobalObject = nil;
}
else {
// remove our reference, which was established at [MONObject new]
// assuming there are no strong external references, the object
// will be dealloc'ed -- but you should not make that assumption
// if you return it.
[GlobalObject release], GlobalObject = nil;
}
}
So if NonRetainedOwnership is true and you use MRC, then your object would typically be -dealloc-ed shortly after -sharedObject returns (assuming whoever called -sharedObject holds no strong reference). In this case, 'shortly' means the pool will often be drained a few frames back in your current callstack, often in AppKit or UIKit when you are on the main thread since I don't see many people explicitly create autorelease pools on the main thread. borrrden said after "1/60th of a second", and the assumption there is that the object is created and autoreleased in the main thread's run loop (correct me if I am wrong). The 'Kits create autorelease pools at each iteration of the main run loop, but your program could be running on a secondary thread or there could be an inner autorelease pool, so the lifetime has the possibility to be shorter or longer. Normally, you don't need to think about these things in much depth -- just use a strong reference here since you really have no other way to ensure the right thing happens with this global variable.
If you simply wrote: #autoreleasepool{[[MONObject new] autorelease];} NSLog("Hi"); then the object would (under normal circumstances) be released by the time NSLog were called.
The declaration of variable doesn't matter as such, The thing what matters is when did you assigned an autoreleased object to it, If it is assigned under any autorelease pool than it would drain it else it would be released on program termination by autorelease pool in main method!
The Variable is just a pointer and does not retain the object unless done explicitly, thats why retaining static objects is preferred: Why retain a static variable?
When the pool is 'drained'. This may not happen right away.
Please see a similar question
It depends. If the variable is initialized only once, and should stay around for the lifetime of the application, then no, it shouldn't be released (its memory will essentially be freed when the application exits, anyway). If, however, the value of the static variable changes, then yes, the previous object should be released when the static variable is set to a new object.

Resources