I am writing a simple Obj-c app. So far I've never had to alloc anything and I gave for granted that ARC would take care of memory management.
But now I have to call:
NSImage *myImage = [[NSImage alloc] initByReferencingFile: pathToMyImg];
After I'm done with myImage should I manually dealloc it?
If you’re using Objective-C ARC (which is the default, and you said you were anyway), there is no difference in required memory management between factory method-style instantiation and [[NSImage alloc] init]-style instantiation. Everything you create will be automatically released when the last strong reference goes out of scope (or the object holding the reference’s last strong reference goes out of scope).
If you weren't using ARC, you’d have to manually do [myImage release] when you were done with it, but there’s no reason not to be unless you’re writing code for an older project.
After I'm done with myImage should I manually dealloc it?
The question makes no sense. You are using ARC. Suppose the answer were Yes. How would you do it? You cannot. ARC will not let you give any NSObject memory management commands.
Therefore the answer must be No.
Related
I am getting a bit confused. I am creating an app with storyboard, and running it on iPad 1. the application uses a lot of memory, so reached the 120mb, crashes. accordingly to what I have understood to remove this problem you need to release, dealloc... the point is that with ARC this should be automatic. In fact if I add for e.g.: [label1 release]; it gives me an error. But this ARC automatic release and dealloc does not seem to work! Is this because there are different ways to release with ARC??
You don't need to manually retain/release/autorelease with ARC. However if you have active references to a lot of unused objects they will still remain in memory. Profile your app with Instruments and it will show you how many objects you're creating of each class and how much memory they're consuming.
With ARC you still need to think about memory usage you just don't need to worry as much about memory leaks.
NSObject *bigMemObj = [[BigMemClass alloc] init];
//This creates the object in memory. In both arc and manual counting the retain count is 1
//Do stuff
//Prior to ARC you would have had to call [bigMemObj release]; before setting the variable to nil
bigMemObj = nil
//With ARC you don't have to do anything. The compiler inserts the release at compile time
Also read the documentation on declaring iVars __strong vs __weak.
Without looking at your code it's hard to identify what is consuming all the memory but hopefully that should help you determine where to start looking.
You should implement #autoreleasePool{} inside each method. In essence, each method will look like the following:
-(void)methodName{
#autoreleasePool{
//do method stuff
}
}
This will ensure that, upon exiting the autoreleasePool, memory is properly released.
I can't vote this back up, otherwise I would. I think Alessandro is asking about ARC vs using release and dealloc, not about what he's loading!
So, Alessandro, your understanding is correct that with ARC you don't release or dealloc. Therefore, those won't work if you're using ARC. Also, there is no alternative to release/dealloc, since ARC doesn't use it.
My suggestion would be to look at what you're using in the app that is taking up all this memory. Do you have a large number of pictures, for example, that are very large? Keep any graphics as small as possible, matching the resolution of the iPad. Especially the iPad 1, which doesn't have the "retina display".
You can use Autorelease pools in ARC. Here is some documentation on when to use them:
NSAutoreleasePool Class Reference
Advanced Memory Management Programming Guide: About Memory Management
I'm pretty new to Objective-C, as you may gather, and until recently, I hadn't really understood the need for all this AutoRelease malarky. I think that's mostly because I've started Objective-C with ARC, and haven't had any exposure to doing retains and release.
Anyway, my understanding now is that pre-ARC, if you created an object and needed to return a pointer to it as the returning object of the method/function, you would need to autorelease it, because you are unable to do the "[obj release]" after doing "return obj;"
Worrying about retains and releases isn't an issue with ARC. Does this mean that in our own code, there is really point in creating our own autoreleased objects? Ie, doing [[[Class alloc] init] autorelease]? From what I've gathered, we should still setup autorelease pools, but only because other frameworks or libraries may still return autoreleased objects, but we no longer need to explicitly create autoreleased objects ourselves - is this a fair understanding?
Thanks,
Nick
When using ARC, you do not want to do any memory management yourself. Specifically you will not be calling release and auto release because it does it all for you. In fact, the compiler should probably complain if you try to manage memory yourself.
Instead of [[[Class alloc] init] autorelease]; you'll just call [[Class alloc] init];
I recommend reading this blog post for some really good background on ARC and memory management in general.
Well, your understanding is quite correct. With ARC we do not release or autorelease any more. Just have to make sure that we assign nil (or some other reasonable value) to any reference to objects, which we do not need any more. In the worst case we could still constantly consume additional memory but the memory cannot leak any ore.
And yes, we still maintain autorelease pools for the sake of using framework libraries (linked ones) that may not use ARC.
To answer your question between the lines about the purpose of autorelease. This applies to non-ARC project only, of course.
In the good old days Objective-C did not offer any reference counting but its retain counting. Any allocated memory of objects, that are not retained (or have a retain count of 0) is considered free and may soon be claimed and used by other objects.
This means that every object needs to be retained after its allocation, assuming that you want to keep it around. When the object is not used any more then you need to release it. This comes with two risks. Well, alloc does retain it once automatically.
1) You may forget to release an object that is unused. In the worst case you may even loose all references to an object that stays in memory for ever since.
2) You may still refer to an object hat has been released already and then try accessing it which will most likely end in an BAD_EXC exception.
All this can be quite annoying. In order to get rid of some of these obligations for objects that don't stay around very long, the autorelease was invented. For temporary objects only you alloc it (release-count = 1) and autorelease it. That means that the object will be automatically released (retain count reduced by 1) within the next autorelease circle. But the object remains allocated for your method while it is being executed. Typically the reference variable would be a local one.
Sample:
-(void) myMethod{
AClass *someObject = [[[AClass alloc] init] autorelease];
// use the object
// probably hand it to another object if that takes ownership, i.e. add it ot an Array using addObject:
// don't care any more
}
And that not required any more when using ARC.
I might've jumped into Objective-C a little too fast and assumed I knew enough about memory management to dive in. Turns out I wasn't.
Fast forward a bit and I've caught up ... for the most part. One of my last remaining questions regards the #property/#synthesize process and setting those values properly.
I've often seen this:
SomeObject *obj = [[SomeObject alloc] init];
self.obj = obj;
[obj release];
It makes sense, but I wonder if this accomplishes a similar enough thing to be an alternative:
self.obj = [[[SomeObject alloc] init] autorelease];
Would that be acceptable anywhere you might set the value of the #property, obj? Or is direct access to the instance variable preferred over both of those in the init method?
obj = [[SomeObject alloc] init];
Thanks.
EDIT: Definitely related question that discusses half of my question. The autorelease part of my question is referenced in one of the answers, but has not been confirmed.
So my questions still remain:
Is autorelease a valid alternative in this situation?
Can autorelease be used this way in the init method, or should the instance variable always be set directly in the init method?
The only difference is that in your first example, obj is released immediately (although it was presumably retained by the self.obj setter). The two examples are effectively the same.
Note that going forward, we can rely on ARC to deal with releasing objects at the appropriate time, so you can write:
self.obj = [[SomeObject alloc] init];
and let ARC worry about where to put the release or autorelease.
Update: You seem to be asking how things are different inside an -init method. The two things you need to be aware of are:
When possible, you should access ivars directly in -init and -dealloc methods. The idea is to avoid problems that could occur if your accessors are overridden by a subclass. There are a number of other questions here on SO that address this in greater depth, such as:
Why shouldn't I use Objective C 2.0 accessors in init/dealloc?
If you're creating an object in an -init method and assigning it to an ivar, you probably don't want to release it until a later point, such as -dealloc. So yes, it's fine in an -init method to not release the objects you create (so long as you keep a reference to them), but you'll still balance that +alloc with a -release in -dealloc.
I'm currently profiling my app and coming across a few leaks. I've tried releasing objects all over the place where I think they are needed. Each release has crashed the app.
Here's one line that I think is the culprit:
NSDictionary *dicUserData = [NSDictionary dictionaryWithObject:self forKey:#"chapter"];
Just wondering the best way to deal with this. I'm having issues with other leaks too that are kind of similar. It's worth noting that self is a custom class [Dal_Chapter].
Do I need to implement copy or something, call that in the above line and do autorelease on that?
Thanks in advance.
Using convenience methods such as dictionaryWithObject provide an autoreleased instance of the dictionary object. Unless you're retaining it elsewhere this is not where your leak is.
I would check out the static analyser it should be able to point out your leaks for you.
That dictionary will retain self so you shouldn't have to worry about it.
Is the owner of self releasing it ?
Basicly you don't have to do anything whith your dictionnary, but if you want to take control of the memory you'll need to do this :
NSDictionary *dicUserData = [[NSDictionary alloc] initWithObjects:yourObject forKeys:key];
and int your dealloc method,
[dicUserDate release];
But normaly you just have nothing to do... Are you sure that your leak come from your dictionnary ?
always keep all variables release in dealloc method. is it not in proper place it may be crash .check this link click here
3 correlated questions:
1.Do the code snippets below provide the very same results in terms of memory?
NSBundle *bundle=[[NSBundle alloc] init];
[bundle release];
bundle=nil;
and
NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init];
NSBundle *bundle=[NSBundle mainBundle];
[pool drain];
pool=nil;
bundle=nil;
2.Why in
NSBundle *bundle=[[NSBundle alloc] init];
[bundle release];
the retainCount of bundle is 1, not 0?
3.Which is recommended: always use class methods, or always gain ownership by using alloc?
Thanks.
Yes, those should be equivalent in terms of memory management, from the developer's point of view. The frameworks might be doing something behind the scene to hang on to [NSBundle mainBundle], but that's not your concern.
Ignore retainCount. waves hand That's not the method you're looking for. Once you have relinquished ownership of an object, either by invoking release or autorelease, then it is invalid (bad practice) to send more messages to that object. In your example, you alloc an NSBundle, so you own it. That means it has a +1 retain count (I say +1, because it's relative). When you release the bundle, it now has a "0" retain count, which means you no longer own this object (despite whether or not it may still exist in memory), which means you should not send messages to it, under penalty of stuff blowing up in your face.
What's recommended is to use whatever's appropriate for the situation. If you just need a temporary object, then using a class method that returns an autoreleased object is probably going to be just fine. If you need to be absolutely sure that the object isn't going to go away while you're using it, then you can use an alloc/init approach (or retain an autoreleased object) and then just release it when you're done.
In the second example you will create 1 extra object (the NSAutorealeasePool) and because of that the two are not exactly the same in terms of memory. But after the code runs I believe the memory will return to the same state in both examples. I am not really sure but I believe that in the second example bundle is an autoreleased object, so when the pool is drained it gets released.
I believe that when the object gets dealloc'ed the retainCount isn't changed.
It is usually recommended to avoid class methods when you create a lot of temporary objects because they won't get released until the next AutoreleasePool drain is called (and if you don't have an AutoreleasePool inside your method it won't happen for sure until you return from your method - and maybe even later). Otherwise you should use the one that feels better for you. I personally prefer allocating them. It is also important to remember that if you want the autoreleased object (the one returned from a class method) to stick around even after you return from the function to retain it.