iPhone - Is there a way to know if a reference is (still) valid? - iphone

Let's say I assign an instance var with an object given in parameter. I don't know what this object is, so I don't want to retain it. But, that reference I have to that object can be invalid at some time, for example if the object is released, or is about to be released (autorelease pool). So, inside my class instance, can I know if the reference I have kept into an instance variable can be used without any risk of crash?

You should retain it and release it when you no longer need it. That is exactly what retain is for.

Kris Van Bael is right, no matter if you know what the object is, if you want to have ownership of it (if it's up to you to ensure that the object is alive), you must retain it. Release it when you don't need it, and set the reference to NIL (for security).
But their is an exception !
Sometimes you don't want to have ownership, the most common example is the delegate.
You don't want to retain your delegate, because it probably already retains you, and if both objects release each other in the dealloc method, your app will leak.
But in this case, you shouldn't care about the delegate being deallocated : the delegate should set your "delegate" property to nil in it's dealloc method.
So
if you have ownership on the object : retain, no choice !
if the object has ownership on you : assign, and don't worry !

This approach is really dangerous. If your app is not able to track object life cycle, then you must change the code in order to have control of this.
Anyway answering to your question: you can protect your instance variable by extra retaining it in your class and then releasing it when it is no more needed. So you don't need to do the check you are asking for.

You should set any released reference to NIL and check for NIL.

Related

ARC delegate issue

I need to download some images from server. So I created a seperate class to handle NSURLConnection delegates.
At the end of didFinishDownloadingData, I called a delegate method like [(id)delegate performSelectorselector(finished:) withObject:receivedData]
I have a view controller called ListImages.
I created the above connection class from ListImages class and assigned connection.delegate = self. After image loaded from server the method -(void)didFinishDownloadingData:(NSData *)data; was called successfully, and I could display that image.
My problem starts now. To handle some common tasks, I created a new class called SharedMethods which is a subclass of NSObject. I allocated connection class as
Connection *conn = [[Connection alloc]init];
conn.delegate = self;
[conn startDownload]; //called a method which starts nsurlconnection.
I am using ARC so not released that object. My applicaion got exception in method, (In Connection class)
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[(id)delegate performSelectorselector(finished:) withObject:receivedData]; //Got an exception in this line
}
The exception was [SharedMethods retain] message send to deallocated object. I dont think I have released anything because I am using ARC.
There was also a problem while callingUIAlerView delegates inside a Class which is a subclass of NSobject. It is not called any how. My doubt is, is there any problem with using a NSObject sublass? Is there anything to consider when using NSObject sublass ?
Thanks in advance.
Using ARC doesn't mean than objects never receive the release method, or that they never get deallocated. It just means that you don't have to make explicit calls to retain and release, and that happens automatically.
The problem here is that your objects are getting deallocated because no one is owning them. Your specific problem is that SharedMethods is being deallocated because it's not getting retained, but I can't show you how exactly that's happening because you didn't post the relevant code.
I can, however, show you that you're not managing your Connection properly, and hopefully that can help you figure out what you're doing wrong with SharedMethods.
So you create Connection with alloc init, which with retain-release code would give it a retain count of 1, but since you're not using ARC anymore that's not really relevant. Unless some other object asserts ownership of the Connection, ARC will automatically insert a call to release to bring the retain count back to 0 (it's kind of like if ARC automatically inserted an autorelease).
Since you don't assign Connection to a strong or retain property, or put it in a collection, no other object is asserting ownership to it. So once execution reaches the end of the scope where the variable conn is defined, it will get released and deallocated.
So in ARC, much like in manual retain-and-release code, you still need to make sure objects are owned by some other object in order for them to stick around. The only difference is that you don't need to manually call retain and release, you just have to think about the object ownership graph—which object is owned by which other object—and make sure that any object you want to stick around is owned by some other object.
So to reiterate, you need make sure that SharedMethods is owned by some other object.

What happens after I release a deallocated object?

I created
object *Obj = [[Obj alloc] init];
Obj retain count is 1. After I release it, the object is deallocated.
If I try to release the object again, what will happen?
EXT_BAD_ACCESS most likely since your object reference is no longer valid.
The code may crash. But it may just as well work most of the time.
You brake a rule, you may get caught. But you may just as well get away with it, living in constant fear that you may get caught later on.
There’s an important distinction to be made here: you can’t release the object again, because the object no longer exists. If you send another message to the variable (be it release or any other message), the behaviour is undefined because the variable is no longer known to point to a valid object. (It’s possible that the address the variable now points to will have been reused for a different object, in which case it may not crash, but of course that’s still a bug.)
Once the retain count of an object reaches 0, it is released, and all further attempts to access it will result in random behaviour.
If you use autorelease instead, the retain count will not be lowered, and the object will be put in the autoreleasepool. The object will only lower its retain count once it reaches the autoreleasepool drain command, which is usually done on a much higher level in a much broader scope. If you really need the object after the autoreleasepool is drained, you should retain it before drain is executed, or else it will have exactly the same behaviour as in my first paragraph.
Get EXT_BAD_ACCESS. Because of you are already release it and now try to release again.
your object reference is no longer valid.

Do you need to release parameters of methods at the end of them in Objective-C?

If I have a parameter passed to a method, do I need to release the parameter at the end of the method?
No. Think NARC: "New Alloc Retain Copy". If you are not doing any of those things, you don't need to release.
Please read the Cocoa memory management guidelines. The following rule is relevant to your question:
You take ownership of an object if you create it using a method whose name begins with “alloc” or “new” or contains “copy” (for example, alloc, newObject, or mutableCopy), or if you send it a retain message. You are responsible for relinquishing ownership of objects you own using release or autorelease. Any other time you receive an object, you must not release it.
Clearly you did not obtain the parameters by creating them (in your method). So the only part that you need to worry about is whether you retained them in the method. If you did, you must release or autorelease them. If you did not, you must not release or autorelease them.
You need to release them only, if you retain them in your method. The convention is, that the caller is responsible to make sure, that the objects passed as arguments live at least as long as the call is active.
Unless you're working directly with foundation objects, you should be delegating all this to ARC by now.

Any way to check if an instance is still in memory?

Example: I have a view controller and get rid of it. But there's still an variable holding it's memory address. Accessing that results in EXEC_BAD_ACCESS. Of course. But: Is there any way to check if that variable is still valid? i.e. if it's still pointing to something that exists in memory?
You need to read this again:
Cocoa Memory Management Guidelines
In short, if you want something to stick around you must retain it.
If you want something to go away and you have previously retained it, you must release or autorelease it.
You must never call dealloc directly (except [super dealloc]; at the end of every one of your dealloc methods).
You must never release or autorelease an object that you did not retain.
Note that some methods do return retained objects that you must release. If you alloc an instance of a class, that implies a retain. If you copy and instance, the copy is retained.
If you are ever tempted to use the retainCount method, don't. It isn't useful. Only consider retain counts as a delta; if you add, you must subtract, but the absolute value is an implementation detail that should be ignored.
(In other words, even if there were ways to check for an object's validity definitively -- there aren't -- it would be the wrong answer.)
Oh, and use the Build and Analyze feature in Xcode. It does a very good -- but not quite perfect -- job of identifying memory management problems, amongst other things.
That's what the entire memory management model is set up for - if you call retain at the right times, and release and autorelease at the right times, that can't happen. You can use NSZombie to help you debug.
Use "NSZombieEnabled" break point.
For this reason only all strongly recommend us to use accessors. If your object is released anywhere, it will get assigned to nil, and there will be no harm if you call any API or method on Nil object. So please make a habit of using Accessors.
you just add this NSZombieEnabled Flag as an argument to your application in build settings. and enable it. Now you run your application in debug mode. If any such crash is about to occur, this breakpoint will show you which object is freed and where it is crashing.
Cheers,
Manjunath
If by variable, you mean whether the pointer to your object still references valid memory then:
MyClass *myVariable = [[MyClass alloc] init];
//Tons of stuff happens...
if (myVariable != nil)
//Do more stuff

Do I need to explicitly alloc my NSNumber?

I am defining a number, as follows:
NSNumber *nn0 = [NSNumber numberWithInt:0];
It works fine without any alloc. My understanding is that if I use numberWithInt, alloc and init are called automatically.
If I try to release at the end of my function, I run into problems:
[nn0 release];
I get a runtime error.
My question is: if I use numberWithInt to initialise the NSNumber, do I have to do any memory management on it?
The "convenience constructors" for a lot of types produce an object that is automatically "autoreleased" - i.e. the new object will be retained by the current NSAutoreleasePool. You don't need to manually release these objects - they will be released when the current NSAutoreleasePool is released/drained.
See this page for a description of convenience constructors, and how to mange the memory for these.
http://www.macdevcenter.com/pub/a/mac/2001/07/27/cocoa.html?page=3
Just follow the core memory-management rule: If you "own" the variable, you have to eventually relinquish ownership. You take ownership by: creating the object (alloc/new/copy) or specifically taking ownership (retain). In all these cases, you're required to release it.
If you need the object to stick around, you need to take ownership of it. So if you know you only need the number for this method (like to pass it into an array or whatever), use the convenience method and just leave it at that. If you want to keep the number for some reason (and instance variable, for example), then you can safely alloc/init it.
If you release something that you don't own, you will get a runtime error.
The rule is simple, with very few exceptions:
If the selector returning an object has the word "new", "alloc", "retain" or "copy" in it, then you own the returned object and are responsible for releasing it when you are finished.
Otherwise you do not own it and should not release it. If you want to keep a reference to a non-owned object, you should call -[NSObject retain] on that instance. You now "own" that instance an must therefore call -[NSObject release] on the instance when you are done with it. Thus you do not own the instance returned by -[NSNumber numberWithInt:] and should not call -release on it when you are done. If you want to keep the returned instance beyond the current scope (really beyond the lifetime of the current NSAutoreleasePool instance), you should -retain it.
In RegEx terms, Peter Hosey lays it out very nicely in his blog. You own the returned object instance if the method selector matches this regex:
/^retain$|^(alloc|new)|[cC]opy/
Of course, the definitive reference is the Memory Management Programming Guide for Cocoa.