performSelector: afterDelay: without retaining the target? - objective-c

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.

Related

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.

Object going out of scope, but delegate is set, using ARC

I'm so very sorry for the unclear title, but I can't explain it shortly.
I am basically wondering what happens if you use ARC and you have a method like this:
- (void)fooMethod:(NSURLRequest *)fooReq
{
NSURLConnection *fooConn = [NSURLConnection connectionWithRequest:fooReq delegate:self];
[fooConn start];
}
So fooConn goes out of scope at the end of the fooMethod, but will I still receive callbacks? In other words: because there aren't any more references, will it get dealloc'd (or something like that) immediately, or will it stay in memory and handle the request because the delegate is still set?
That totally depends on what NSURLConnection does behind the scenes. If the retain count drops to zero, then fooConn will be dealloc'ed still and one would assume no more callbacks would be made then.
Now, I think that NSURLConnection behind the scenes does get retained somewhere in the hierarchy of things so you would in fact receive callbacks. However with NSURLConnection I usually keep a strong reference to it lying around to be on the safe side. After all, you as the caller of it want to own it and you want to ensure that you will keep getting the delegate callbacks and not be at the mercy of whatever happens to it under the hood.
So, in short, if I were you I'd keep a strong reference to it to ensure you won't have to worry.
From the Apple docs:
- (id)initWithRequest:(NSURLRequest *)request delegate:(id < NSURLConnectionDelegate >)delegate startImmediately:(BOOL)startImmediately
The connection retains delegate. It releases delegate when the connection finishes loading, fails
fooConn is a local variable without any ownership qualifier so ARC will infer it as strong. Therefore ARC will retain the value returned by connectionWithRequest:delegate: when storing it into foxConn; and when exiting fooMethod: ARC will clean up by releasing fooConn.
That the delegate references the current instance will have no effect on this.
If you wish the NSURLConnection to exist after fooMethod: returns one way is to store it into an instance variable (which ARC also infers as strong, so no ownership qualifier required there either). If you do this when the class instance itself is no longer reference ARC will release the NSURLConnection.

after self released

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.

Suicide: Objective-C objects calling their own -dealloc methods on themselves

Is it good practice for an object in Objective-C to commit suicide? That is, for an object to declare [self dealloc] where -dealloc permits an orderly wind down as usual? What are the principal risks?
As it happens I have a specific example, a custom timer object that extends NSObject and comprises an NSTimer instance and an NSUInteger which is set to limit the number of times the timer fires. When time is up the object tells the timer to -invalidate and then commits suicide by calling its -dealloc method. As this is automatic we have no worries about having to track the object or crucially knowing when is the correct moment to deallocate it.
For a more detailed explanation see my post over here.
You shouldn't be calling -dealloc. Instead call [self release] so the reference count goes to 0 and let the system call -dealloc.
Is it good practice for an object in Objective-C to commit suicide? That is, for an object to declare [self dealloc] where -dealloc permits an orderly wind down as usual? What are the principal risks?
No.
The only time you should ever write a call to dealloc is to send dealloc to the super object in the dealloc method of one of your classes. No exceptions.
If you try to send dealloc to an object at any other time, you risk leaving other objects with dangling pointers. Don't do it.
Should you ever send release to self? That is a different matter, but you should still follow the Memory Management Rules. If you have sent retain to self, then at some point you will need to send release to self. There is one exception which is in init, if initialisation fails you have to release self and return nil (I guess you could claim that alloc has sent retain to self).

Memory Management Question in Objective C

I have a tableviewcontroller where I populate some data from a sqlite db and for each row, I download a file from a http server and cache it locally. I cache it only when the "detailsview" is opened. And the detailsview responds back to this table through a delegate after the file download is complete.
But, when this tableview itself is popped out of the navicontroller., the call to delegate fails with a EXEC_BAD_ACCESS
I called [_delegate retain] in the setDelegate of the details view and everything works fine, but I'm not sure whether this will leak memory...
Could anyone advise?
Your delegate is getting released prematurely, and sending a message to an invalid object will call EXEC_BAD_ACCESS. Retaining it will fix the problem, but in general it's good practice to not have an object retain its delegate, as there is the potential for retain cycles, so you might need to rethink your structure. If you're releasing your delegate when the view is dealloc'ed, you need to remove it unless you're also retaining the delegate in setDelegate:.
Generally, delegates are not retained to avoid retain cycles. If the delegate may be released before you, then it is the responsibility of the delegate to clear your reference before it is finished being deallocated (eg in its dealloc).
However, if any property is set to "retain" or "copy", then you would retain/copy it in the setter (or use #synthesized setters which will do it for you), and release it in dealloc to avoid leaking. As said above though, that may lead to a retain cycle so that neither object ever gets deallocated.
I would suggest you turn on some memory debugging with environment variables NSZombieEnabled and NSAutoreleaseFreedObjectCheckEnabled and see if it tells you which object is being over released.