after self released - objective-c

I'm using a third-party Objective-C library that makes a web request in a background thread, then returns the result by using [self performSelectorOnMainThread:...] which then calls a delegate method. I understand that I need to nil the delegate reference before releasing the delegate, but I was wondering what happens if this requesting object itself gets deallocated while the background thread is running. Will this internal self reference get set to nil so that the -performSelectorOnMainThread: call is harmless, or is there a potential for a crash here?

As far as I understand your scenario (but possibly you should include some code), the statement:
[self performSelectorOnMainThread:...]
should be the last one to be executed in your thread (since it is the way to return the result of your thread, it is still part of the thread selector passed to NSThread).
If it is reasonably so, then consider that when you first detach an NSThread, you pass it a target object (your self) and the NSThread will retain it as long as the passed selector hasn't completed. This will include your [self performSelectorOnMainThread:...], so, unless someone messes heavily with releases, there should be no chance for self to be deallocated before [self performSelectorOnMainThread:...] is executed.
If your question was exactly what happens if someone messes with releases, I will give this a second thought.

If your object is deallocated before the method on the main thread completes, you have a memory management problem. The performSelectorOnMainThread:… family of methods cause the receiver to be retained until it has done its work, so the only way it could be deallocated is if you're over-releasing the object.

Related

In Objective-c is performSelector executed inline or is it posted for execution as a different event?

There are plenty of reasons why this matters. Here's a simple example if you weren't using ARC.
[instance performSelector:selector withObject:objectA];
[objectA release]; // Did the selector actually finish executing
// in the line above so everyone's done with objectA
// or did the selector merely get scheduled in the line
// above, and is yet to execute, so objectA had better
// not be released yet?
I've done some research and context clues seem to point to selector getting done inline. But I haven't seen any definitive statement anywhere I've looked, that states it gets executed inline.
performSelector:withObject: is executed synchronously (block until the method finished).
Use performSelector:withObject:afterDelay: to execute method asynchronously on main thread (return immediately and execute later).
Use performSelectorInBackground:withObject: to execute method asynchronously on background thread (return immediately and execute on different thread).
Note:
performSelector and its friends should be avoid because it is undefined behaviour if you use them on method with incompatible method signature.
The aSelector argument should identify a method that takes no arguments. For methods that return anything other than an object, use NSInvocation.
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/index.html#//apple_ref/occ/intfm/NSObject/performSelector:
Did the selector actually finish executing in the line above so
everyone's done with objectA or did the selector merely get scheduled
in the line above, and is yet to execute, so objectA had better not be
released yet?
It doesn't matter, for memory management purposes. Memory management in Cocoa is local -- you only need to care what your function does; you don't need to know, and shouldn't care, what other functions do internally, to manage memory correctly (ignoring retain cycles). As long as you're done with your owning reference, you should release it. It doesn't matter to you if other people are done with it.
This is because, according to Cocoa memory management rules, any function which needs to store it for use beyond the function call is required to retain it and release it when it's done (because the function cannot assume that the object lives beyond the calling scope otherwise). Any function which uses an argument asynchronously (e.g. performSelector:withObject:afterDelay: etc.) does indeed retain the object and release it when it's done.
Alternately, think about it this way: How does ARC work? How does ARC know whether a function uses its argument synchronously or asynchronously? It doesn't. There is no annotation that tells the compiler whether a function uses something synchronously or asynchronously. Yet ARC does it correctly. That means you can too, without knowing whether the function uses its argument synchronously or asynchronously.

Is dealloc guaranteed to be called on the same thread that created the object?

Is dealloc guaranteed to be called on the same thread that created a NSObject instance? For example, if I call [[MyFluffyBunny alloc] init] on the main thread, is dealloc guaranteed to also be called on the main thread, or can it be called on any thread once MyFluffyBunny is no longer retained?
I see sporadic crashes in my app that points to that it's not guaranteed, but I've been unable to find any documentation confirming it.
The object is deallocated on whatever thread releases the last strong reference to it. That is, whatever thread calls -release the final time. It is actually during that -release call that the object is deallocated.
The documentation for the -release method in the NSObject protocol says:
Decrements the receiver’s reference count. … The receiver is sent a dealloc message when its reference count reaches 0.
The Advanced Memory Management Programming Guide: Practical Memory Management article includes this among the reasons to not use -dealloc to manage scarce resources:
Cleanup logic being executed on the wrong thread.
If an object is autoreleased at an unexpected time, it will be deallocated on whatever thread’s autorelease pool block it happens to be in. This can easily be fatal for resources that should only be touched from one thread.
There is no such guarantee and, in fact, it makes for some subtle bugs when using KVO (and bindings on OS X).
You can see it in action fairly easily by creating an object that logs [NSThread currentThread] during init and dealloc, then running code such as:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
Testing *testing = [[Testing alloc] init];
dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^{
NSLog(#"Use testing in background: %#", testing);
});
testing = nil;
return YES;
}
I'm unaware of a line in the documentation that says anything about this, but here are some points of logic:
If you can't find a guarantee somewhere, assume it doesn't exist. (It sounds like you're aware of this already, and are hoping beyond hope that somebody else can point you to something that gives you the answer you want)
That requirement cannot be possible because you can construct something on a thread, then end that thread, then have the last reference go out of scope somewhere else in some other thread. It wouldn't be possible at this point to dealloc on the old thread because it no longer exists.

Dealloc method isn't called when i release perticular object

I have created an object using alloc/init method, and after I release it -dealloc should be called immediately as per documentation. I set a breakpoint on -dealloc method but it isn't hit, and my -dealloc method is not called.
Please tell me what is the reason behind that, and what is use of dealloc method in objective c ?
The -dealloc method is not always called when you expect it to be called. The runtime might also have issued a -retain on your object for internal reasons.
It's also possible that you have (directly or indirectly) caused an extra -retain to be issued. If the retains/allocs and releases are not balanced, you'll never see -dealloc called. It helps to turn on the Static Analyzer, to make sure your calls balance.
Just follow the memory management rules, don't second guess the runtime, and let the memory management system do its job.
The answers to When does dealloc method call? may help you understand what you're seeing.
because it still has reference. that means its reference count not reached to zero. i don't know your code, where it is referencing. but it is not calling that means somehow still it has reference. it may be because of strong relationship or parent-child relationship
all Objective-C objects are allocated on the heap, so they must
therefore be deallocated somewhere if you are not to run out of
resources.
This gave way to the reference counting method, which is still used
today: each object keeps count of any references held to it. If you
receive an object and you want to keep it, you retain that object,
incrementing its reference count. When you are done with it, you
release it, which decrements its reference count. Once that count
reaches zero, it is inferred that no one is referencing the object and
it is automatically deallocated using the -dealloc method.
Additionally, an object could be told to “release at some point in the
(hopefully) near future” using autorelease pools. The idea is that
somewhere on the stack (typically at the start of a thread or while
responding to input events) an autorelease pool is created and pushed
onto a stack. Any object can then be sent an -autorelease message, and
it is assigned to that pool.
When the pool object is deallocated, it simply sends a -release
message to all its assigned objects. That way, any objects that are no
longer used (i.e. they haven’t been explicitly retained) are then
deallocated.
The dealloc is called (at more cases) whenever your object is released. You can't directly call this method.
#interface myViewController:UIViewController
{
NSString *myStr;
}
#end
Here the dealloc method in the #implementation of myViewController will be called (at most cases) when the myViewController object is released, not when myStr is released.
Although you don't have to use if you ARC.

performSelector: afterDelay: without retaining the target?

I've got a class which uses NSURLConnection to open a long-running connection to a server. When the connection's closed, either in connectionDidFinishLoading: or connection:didFailWithError:, I want to wait 15 seconds then retry the connection.
At the moment I'm using [self performSelector:#selector(restartConection) withObject:nil afterDelay:15.0];, but this leads to the undesired situation that when the object is released by its creator, the performSelector and NSURLConnections perpetually retain 'self', and it never gets deallocated.
How can I do this without perpetually retaining the object? Any help'd be much appreciated.
Thanks, -Alec
I think your only option is to send
[NSTimer cancelPreviousPerformRequestsWithTarget: object];
at some point, probably, before releasing the object. If the timer hasn't been scheduled, this is a no-op, but is not free performance-wise.
You cannot avoid retaining the object. It is retained in order to save you from ugly crashes when in the next main loop cycle the runtime is going to call your selector on the released object.
If you really insist on having your object released immediately without waiting for your delayed selector, I would suggest you to create a separate proxy class. Say your class is called A, create proxy class B which will have a weak reference to your class A (i.e. __weak A* a) and restartConnection selector which will check if the weak reference is valid. If so it would invoke restartConnection on your A object. Then, do, of course, a delayed selector on B's restartConnection
But first of all, I would really suggest that you reevaluate whether you really cannot live with the retain.

Objective C: Memory management in Block cases

I am wondering if I am using blocks as shown in the code below
__block Loader *loader = [[Loader alloc]initWithResourcePath:self.resourcePath];
[loader setCompletionHandler:^(NSArray *anArray){
self.answerArray=anArray;
[self reloadData];
}];
[loader getObjects];
My question is with regards to memory management. The analyzer tells me that there is a potential leak (since I did an alloc/init for my loader). How can I stop the leak here? I tried to release the loader at the end but that causes my app to stop functioning. Any advise is appreciated here
Several issues:
there is no reason for loader to be declared __block; you aren't re-assigning in the block and, thus, the __block is pointless.
the leak is because you alloc/init the loader, but never release it
do not name methods getSomething; the get prefix is reserved for methods that return stuff by reference. Just call it objects. If it is supposed to trigger the load, then call it load or performLoad.
If it is asynchronous, then getObjects is pointless. If synchronous, then the completion block is pointless.
If loader is to be used synchronously, release it at the end of the method. If it is asynchronous, then the completion block could release it. Note that the use of __block in this case is still pointless; while referring to loader in the completion block will create a retain cycle, it will be broken when you explicitly Block_release() the block in your loader (because you must have done a Block_copy() when setting the completion handler if it is to be used asynchronously in the first place).
If you plan to use loader outside of the function calling your block, it is highly possible that you need to store it in a ivar of your controller (I guess, it is a controller, but I don't know what kind of class owns the code you shows). Once you do that, you can release it in your dealloc.
The reasoning is that loader should live across several methods and runloop cycles, so a local variable will not do.
Otherwise, just release it at the end of the block, once you have done with it.
If this does not seem right to you, then possibly more code is needed.
I'm going to make some assumptions: 1) The completion handler (block) is used by method getObjects. 2) getObjects is asynchronous (it returns to the caller right away though it continues to process).
With these assumptions you can't send release after sending getObjects because getObjects is still using the completion handler.
Try sending a release or autorelease at the end of the completion handler. That should free loader provided reloadData is not also asynchronous.