This maybe too basic but I couldn't find an exact answer. I'll be happy to delete/close this post if anyone point me to similar posts.
I want to call method "getString" to return a formatted string and set to my label like this:
-(NSString*) getString {
NSString *result = [NSString stringWithFormat:#"blah blah %#", someOtherString];
return result;
}
-(void) viewDidLoad {
someLabel.text = [self getString];
}
This code worked for me, but I am concerned that result is allocated by a convenient method thus may be auto-released before it got retained by the label. Is it true? If so, when exactly would an object from convenient method get released?
Second question, if in case I have to use [NSString alloc] to create my own string object. Where and how should I release it?
Thanks in advance
Leo
It isn't true that the object will be autoreleased before you retain it. The details of when the pool gets drained are unimportant to answer this question, except that it can't happen during your code unless you call drain or release on the pool. If your function calls another function, except in some specific edge cases both the function you call and the function you called from need to exit before that thread can do anything else. The autorelease pool is thread-specific.
To answer your second question, if you alloc an object you should release it when you've finished using it. Simple as that. That includes when you pass it to other code that needs it, because it should be up to that other code to claim ownership if it needs to.
This code worked for me, but I am concerned that result is allocated by a convenient method thus may be auto-released before it got retained by the label.
Yes, it will be autoreleased because it is returned by a method whose name does not contain new, alloc or copy. No, this won't happen before the calling method viewDidLoad returns.
In fact, the autorelease-pool, to which it's added will probably be the one set-up and teared-down by the runloop, so nothing is going to happen to it until the end of the current iteration through the runloop.
Related
I'm working someone else's code. I've never encountered something like this before:
return [[[NSObject alloc] init] autorelease];
Can someone tell me what this means and why someone would use it? Just to be clear, I'm not asking about the autorelease portion. I would have the same question about this code:
-(id)someMethod
{
lots of lines of code
...
return [[NSObject alloc]init];
}
The autorelease feature indicates that you want to release this object in the FUTURE, but not now because you still need to access it. With the release cycles and releasing of the pool of memory, autorelease is an extremely useful tool in memory management.
You can refer to: http://developer.apple.com/mac/library/DOCUMENTATION/Cocoa/Conceptual/MemoryMgmt/Articles/mmPractical.html#//apple_ref/doc/uid/TP40004447 for information on autoreleasing.
Here's a link! What is the difference between releasing and autoreleasing?
Hope this helped!
The object is being allocated, initialized and then added to an autorelease pool.
Quoting Apple documentation (the link above):
Autorelease pools provide a mechanism whereby you can send an object a
“deferred” release message. This is useful in situations where you
want to relinquish ownership of an object, but want to avoid the
possibility of it being deallocated immediately (such as when you
return an object from a method). Typically, you don’t need to create
your own autorelease pools, but there are some situations in which
either you must or it is beneficial to do so.
TL;DR if nobody will retain the object soon, it will be released on the next iteration of the run loop.
It's hard to tell without knowing any details why would anyone want to allocate an NSObject in the first place. I'd suggest searching the project for that method's usage examples and see what happens with the object next.
It is just returning an autoreleased object for convenience. This means that when you use the function you do not have to append autorelease message to it generally speaking. You may always want certain objects to be autoreleased.
As an example, many of the included convenience ("factory") methods in Objective-C return an autoreleased object. You are probably familiar with [NSString stringWithFormat:__FORMAT__] which returns an autoreleased NSString. Take a look at http://memo.tv/archive/memory_management_with_objective_c_cocoa_iphone
As an example of why a function might return an object, consider a synchronous URL request, where you may or may not care about a response, or a function like the following:
- (NSString *)modifyObject:(MyObject *)o {
o.mySettableProp = #"MODIFIED!";
return [o description];
}
If I have a class named Foo and I have this function + getIds that should return ids. Would the correct signature of + getIds look like this:
+ (NSArray *)getIds {
NSMutableArray *ids = [[[NSMutableArray alloc] init] autorelease];
return ids;
}
What I'm wondering is that if I should use autorelease on *ids? There is no other way I assume? I can't do [ids release] after the return statement right?
You can send autorelease message along with alloc, init messages. You can also do, return [ids autorelease]; Note: You should not do both at the same time ;-)
You can not return [id release], because release method itself returns nothing.
The typically-correct memory management for returned objects is to have the called method set it as an autoreleased object, except when the method name contains "copy", "new" or "alloc". In those cases (copy/new/alloc), the returned object is retained, and the caller owns it (i.e. the caller is responsible for making sure they are released).
The code you wrote in the question will do the correct thing - it will return an autoreleased object.
When the caller gets the NSArray back, they can use the object as much as they like, and if they don't need the object in future calls, then they don't need to do any extra memory management. At the end of the run loop, the NSArray will be released, which is the desired behavior. If the caller does need the object to live longer, then they have to call retain on it (or something equivalent to that, such as calling something else that calls retain on it), and then they take the responsibility to call release on it later.
Useful stuff:
Apple's iOS memory management guide
My personal memory management guidelines (shorter, more biased)
Understanding run loops
Also, this will all go away when ARC (automatic reference counting, in iOS 5) becomes the norm.
You are already autoreleasing the array, so calling autorelease a second time would be an error that might result in a crash. The fact that you can't do a release after the return (you've left the function by then) is one of the reasons autorelease exists.
About whether the method should return an autoreleased as opposed to a retained object: Only methods that start with alloc or new or contain copy (as in mutableCopy) shall return retained objects. All other method shall return autoreleased objects.
When a method returns an object that is taken from and NSMutableArray does the object must be autoreleased? Check the following method. Also should I autorelease the nil value?
-(NSObject*)getElementByID:(NSString*)ID{
for(int i=0;i<[elements count];i++){
NSObject *element = (NSObject*) [elements objectAtIndex:i];
if([element.key isEqualToString:ID]){
return [element autorelease];
}
}
return nil;
}
You must not autorelease element because you are not an owner of it (you have not put a retain on it). You would have become an owner of it if you acquired it using alloc, new or retain. Since you acquired this object calling objectAtIndex:, you do not own it. See Three Magic Words. Calling autorelease here will cause a crash later do to over-release.
Your method name is incorrect and breaks KVC. A method that begins with get must take a pointer that will be updated with the result. This should be elementForID:. As noted above with the three magic words, naming in ObjC is very important to writing stable code
As a side note, it is traditional to use id is most cases rather than NSObject*. They mean slightly different things, but typically id is correct.
You never need to do any memory management related things to nil. So, no, you should not send autorelease to nil.
You also should not need to send autorelease to the element object that you are returning from your elements array. That object you are returning will remain in memory by virtue of elements itself having retained it. If the calling method would like to retain the value that you return, it may. But if that calling method only uses the returned value within its own scope, it is safe for it to do so without retaining it.
I want to check if an object has some count or not Here is my testing code
NSMutableArray *array=[[NSMutableArray alloc]init];
if(array)
{
NSLog(#"hiiiiiii");
}
CASE-2
NSMutableArray *array=[[NSMutableArray alloc]init];
[array release];
if(array)
{
NSLog(#"hiiiiiii");
}
Here in both cases i got same output as printed "hiiiiiii".
Can anyone tell me how will i check if my object need to release or already released.
I know that i should have track of my object's counters but i am at a stage where my code is too much complexed and i need help..
Please help..
ALso tell that how much memory leak is allowed by apple?
There is no way to check if you "should" release an object. Doing something like "if(object)" only checks the pointer to the object. It will return true even if the object it was pointing to was destroyed a long time ago. This is what happens in your second case. The object is destroyed when you call release, but the pointer is still pointing at something, so it returns true. It will only return false if the pointer is set to nil.
However, there is a simple set of rules for calling release. If you ever call "alloc", "new", "copy", "mutableCopy" or "retain" on object, you must always call "release" or "autorelease" on it. That will prevent any memory leaks.
Apple does not have a publicized amount of memory leaks allowed. It is always safest to eliminate any known memory leaks; plus, it will mean better performance for your customers.
In your second case you are releasing the NSMutableArray but still it store a non zero value although it's no longer for use (To call function OR fetch value).That the reason your if condition got true.
Just remember whenever you call release on any object, Do'nt forget to assign nil to that, So your second code should look like below.
CASE-2
NSMutableArray *array=[[NSMutableArray alloc]init];
[array release];
array = nil;
if(array)
{
NSLog(#"hiiiiiii");
}
There is a simple rule of memory management in Object-C if your alloced or retain any object you must call release on that,
Read memory management Guide from Apple.
Example:
- (NSString*) title {
return [[title retain] autorelease];
}
The setter actually retained it already, right? and actually nobody should bypass the Setter... so I wonder why the getter not just returns the object? It's actually retained already. Or would this just be needed in case that in the mean time another objects gets passed to the setter?
From here http://www.macosxguru.net/article.php?story=20030713184140267
- (id)getMyInstance
{
return myInstanceVar ;
}
or
- (id)getMyInstance
{
return [[myInstanceVar retain] autorelease] ;
}
What's the difference ?
The second one allows the caller to get an instance variable of a container object, dispose of the container and continue to play with the instance variable until the next release of the current autoreleased pool, without being hurt by the release of the instance variable indirectly generated by the release of its container:
aLocalVar = [aContainer getAnInstanceVar] ;
[aContainer release];
doSomething(aLocalVar);
If the "get" is implemented in the first form, you should write:
aLocalVar = [[aContainer getAnInstanceVar] retain];
[aContainer release];
doSomething(aLocalVar);
[aLovalVar release];
The first form is a little bit more efficent in term of code execution speed.
However, if you are writing frameworks to be used by others, maybe the second version should be recommanded: it makes life a little bit easier to people using your framework: they don't have to think too much about what they are doing…;)
If you choose the first style version, state it clearly in your documentation… Whatever way you will be choosing, remember that changing from version 1 to version 2 is save for client code, when going back from version 2 to version 1 will break existing client code…
It's not just for cases where someone releases the container, since in that case it's more obvious that they should retain the object themselves. Consider this code:
NSString* newValue = #"new";
NSString* oldValue = [foo someStringValue];
[foo setSomeStringValue:newValue];
// Go on to do something with oldValue
This looks reasonable, but if neither the setter nor the getter uses autorelease the "Go on to do something" part will likely crash, because oldValue has now been deallocated (assuming nobody else had retained it). You usually want to use Technique 1 or Technique 2 from Apple's accessor method examples so code like the above will work as most people will expect.
Compare this code
return [[title retain] release]; // releases immediately
with this
return [[title retain] autorelease]; // releases at end of current run loop (or if autorelease pool is drained earlier)
The second one guarantees that a client will have a non-dealloced object to work with.
This can be useful in a situation like this (client code):
NSString *thing = [obj title];
[obj setTitle:nil]; // here you could hit retainCount 0!
NSLog(#"Length %d", [thing length]); // here thing might be dealloced already!
The retain (and use of autorelease instead of release) in your title method prevents this code from blowing up. The autoreleased object will not have its release method called until AFTER the current call stack is done executing (end of the current run loop). This gives all client code in the call stack a chance to use this object without worrying about it getting dealloc'ed.
The Important Thing To Remember: This ain't Java, Ruby or PHP. Just because you have a reference to an object in yer [sic] variable does NOT ensure that you won't get it dealloc'ed from under you. You have to retain it, but then you'd have to remember to release it. Autorelease lets you avoid this. You should always use autorelease unless you're dealing with properties or loops with many iterations (and probably not even then unless a problem occurs).
I haven't seen this pattern before, but it seems fairly pointless to me. I guess the intent is to keep the returned value safe if the client code calls "release" on the parent object. It doesn't really hurt anything, but I doubt that situation comes up all that often in well-designed libraries.
Ah, ok. from the documentation smorgan linked to, it seems this is now one of the methods that Apple is currently recommending that people use. I think I still prefer the old-school version:
- (NSString *) value
{
return myValue;
}
- (void) setValue: (NSString *) newValue
{
if (newValue != myValue)
{
[myValue autorelease]; // actually, I nearly always use 'release' here
myValue = [newValue retain];
}
}