Do you need to release NSData? - iphone

-(void) func1: (NSData*) somedata
{
//Processing somedata ....
[somedata release]; //is it necessay?
}

You shouldnt release somedata inside your method.
NSData *somedata = [[NSData alloc] init];
func1(somedata);
[somedata release];
Assumptions:
func1 runs on same thread

In this case, no, you should not release your object. You're not the "owner". As a rule of thumb, you need to release an object once you're done with it only if:
You allocated it via [MyClass alloc], as in [[MyClass alloc] init] or [[MyClass alloc] initWithFoo:foo bar:baz].
You got a copy via [someObject copy] or [someObject mutableCopy].
You have retained it before.

You should consider releasing it If you are retaining it in this case. But I am not sure because your question does not provide any idea whether a release is required or not. But generally you will release objects if you take ownership of it.

Related

How to use NSAutoreleasePool

If I use NSAutoreleasePool, every object created inside the pool should never be released mannually?It will be released when the pool is drained?
- (void) backgroundRequest{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
urlList = [[NSMutableArray alloc] init];
target = [[NSMutableArray alloc] init];
{
//do stuff in here
}
[urlList release];
[target release];
[pool release];
}
Are the above lines correct or I should remove [urlList release] and [target release]?
IMPORTANT: I will wait an explanantion and an answer.Thank you
An autorelease pool only works when you have objects using the Autorelease methods.
If you're using this:
urlList = [[NSMutableArray alloc] init];
Then you will want to do your own release, yes. However if you do this:
urlList = [[[NSMutableArray alloc] init] autorelease];
Then you can let the NSAutorelease pool handle that.
If you dont want to release urlList and target, then you can use this code:
- (void) backgroundRequest
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
urlList = [[[NSMutableArray alloc] init] autorelease];
target = [[[NSMutableArray alloc] init] autorelease];
{
//do stuff in here
}
[pool release];
}
Hope this helps you.
The point is that AutoreleasePool takes care of those allocations which have been autoreleased with the keyword autorelease So if you use that keyword then you don't need to release it. It is released when the AutoreleasePool gets released.
If you need more information then please leave me a message below.
I second the answer from #Brayden. I would like to add up to that.
Generally every thread has its autorelease pool. See your .main file for instance. It has got an autorelease pool associated with it. So that way your main thread has got an autorelease pool.
Now when you spawn another thread, ie try to run some methods on another thread, and if your gonna use class methods for common initialization.
eg: NSString *strTem = [NSString stringWithString:AnotherString];
Such is the case where autorelease will be used, and for such functions(methods) you need to have a separate autorelease pool of your own.
Hope this helps some more.

Dealloc objects of another class

Hi I generally create objects of another classes. can you please tel me if this wil be in the auto release pool? or should we release it manually.
if you init copy or new them you'll have to deallocate them if you put an autorlease with the allocation then they will be autoreleased
for example
Foo *foo = [[Foo alloc] init]; //you'll have release it somewhere yourself
And
Foo *foo = [[[Foo alloc] init] autorelease];// this will be autreleased
The simple case is : if you use init, you are responsible for releasing it, either by calling release or by calling autorelease.
e.g.
NSString *myString = [NSString alloc] init]; // You need to release this
...
[myString release]; // Now it's released - don't use it again!
or if you are going give it to someone else
NSString *myString = [NSString alloc] init]; // This needs releasing
...
return [myString autorelease]; // You are finished with it but someone else might want it
However, there's a few other cases.
NSString *myString = [NSString stringWithFormat:#"hi"];
This object is in the autorelease pool already - don't release it!
NSString *secondString = [myString copy];
This object needs releasing - it is not autoreleased.
Rule of thumb : Anything with init, copy or new in the name - you made it, you release it. Anything else will be autoreleased.

ObjectiveC - Releasing objects added as parameters

Ok, here goes.
Being a Java developer I'm still struggling with the memory management in ObjectiveC. I have all the basics covered, but once in a while I encounter a challenge.
What I want to do is something which in Java would look like this:
MyObject myObject = new MyObject(new MyParameterObject());
The constructor of MyObject class takes a parameter of type MyParameterObject which I initiate on-the-fly.
In ObjectiveC I tried to do this using following code:
MyObject *myObject = [[MyObject alloc] init:[[MyParameterObject alloc] init]];
However, running the Build and Analyze tool this gives me a "Potential leak of an object" warning for the MyParameter object which indeed occurs when I test it using Instruments. I do understand why this happens since I am taking ownership of the object with the alloc method and not relinquishing it, I just don't know the correct way of doing it.
I tried using
MyObject *myObject = [[MyObject alloc] init:[[[MyParameterObject alloc] init] autorelease]];
but then the Analyze tool told me that "Object sent -autorelease too many times".
I could solve the issue by modifying the init method of MyParameterObject to say return [self autorelease]; in stead of just return self;. Analyze still warnes about a potential leak, but it doesn't actually occur. However I believe that this approach violates the convention for managing memory in ObjectiveC and I really want to do it the right way.
Thanx in advance.
Ok, here's a suggestion.
MyParameter *param = [[MyParam alloc] init];
MyObject *obj = [[MyObject alloc] initWithParam:param]; // do you know if param is retain'd or not?
[param release];
Why do it this way? This is the pattern used throughout ObjC/Cocoa. You add objects to NSArrays this way:
MyThing *thing = [[MyThing alloc] init];
[myMutableArray addObject: thing]; // this calls [thing retain]
[thing release];
You may also want to try to do this:
MyObject *obj = [[MyObject alloc] initWithParam: [MyParameter parameter]];
where:
+ (id) parameter
{
return [[[self alloc] init] autorelease];
}
that way you don't have to worry about it. This is the same as
[NSData data];
[NSArray array];
I hope that helps. Generally, it isn't a good idea to use init during another method call (like a setter or another init). Hiding it behind a Class Method (+ (id) parameter) means the user knows it'll be autorelease'd.
If you're ever unclear about how many retain's or release's something has, you can always do something like this:
[EDIT]
Caveat: Apparently you should never use -retainCount. I find it useful for teaching learners the basics of retain'd Memory Management, but the point is well taken.
Never Use it in actual code or for performance testing. This is only used to learn what retain does (and I believe it functions properly in this case). It will never give you an intelligent answer for an object which is autorelease'd or further retain'd by a NSArray or Other Foundation/AppKit/UIKit Classes
MyParameter *param = [[MyParam alloc] init];
NSLog(#"param retain count: %d",[param retainCount]); // should be 1
MyObject *obj = [[MyObject alloc] initWithParam:param];
NSLog(#"param retain count: %d",[param retainCount]); // should be 2, if MyObject retains it.
[param release];
NSLog(#"param retain count: %d",[param retainCount]); // should be 1
Also, when you dealloc MyObject, you'll need to release param if you retain'd it during initialization.
The following guide put out by Apple should help you to understand Objective-C Memory Management a little better.
MyThing *thing = [[MyThing alloc] init];
[otherThing methodWithAThing:thing];
[thing release];
or:
[otherThing methodWithAThing:[[[MyThing alloc] init] autorelease]];
or (if there is a "convenience constructor" on the class you're using):
[otherThing methodWithAThing:[MyThing thing]];
MyObject *myObject = [[MyObject alloc] init:[[[MyParameterObject alloc] init] autorelease]];
should be ok, if there is no release in the init (there should definitely not be a release in the init). I often make a class method which makes a autoreleased object. So the code would be:
// using it:
MyObject *myObject = [[MyObject alloc] init:[MyParameterObject defaultParameters];
// in the class implementation of MyParameterObject
+ (MyParameterObject*) defaultParameters{
MyParameterObject* out = [[MyParameterObject alloc] init];
// set some values
return [out autorelease];
}
[[MyObject alloc] init:[[[MyParameterObject alloc] init] autorelease]]
Without knowing what's going on in the init method, this seems fine.
NB, though, that it's more Objective-Cish to spell this "initWithParameterObject:". Though they gag people new to the language, Obj-C's descriptive method names are actually really helpful for code readability.

Question about memory usage

I have the following method:
+(NSMutableDictionary *)getTime:(float)lat :(float)lon {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
[dictionary setObject:hour forKey:#"hour"];
[dictionary setObject:minute forKey:#"minute"];
[dictionary setObject:ampm forKey:#"ampm"];
return dictionary;
}
A lot of the method is chopped off, so I think I need the pool for some other stuff in the method. Here's my question. I know that I need to release the following objects:
[dictionary release];
[pool release];
However, I can't release the dictionary before I return it, but as soon as I return it the rest of the method isn't performed. What should I do?
You could always autorelease the dictionary, thereby ensuring it is kept in memory at least until getTime:: returns. This conforms well to the memory paradigm on Cocoa, where a method which returns an object which it creates (but does not own), calls autorelease on it when it no longer needs it.
Of course, make sure to retain that dictionary in any code that receives it from getTime::.

Simple problem with NSString

I have this userInputstring in the header that will be modified and used by multiple methods in the .m file
.h
NSString *userInputString;
-(void)main;
-(void)method1;
-(void)method2;
.m
-(void)main{
[self method1];
[self method2];
}
-(void)method1{
NSString *localString = #"something";
userInputString = localString;
//do something else with it
}
-(void)method2{
NSString *localString = [NSString stringWithFormat:#"%# insert something",userInputString];
userInputString = localString;
[someOtherMethod:userInputString];//Crash
}
but I kept getting memory leak problems. What's the proper way to set it up? Im new to objective c.
I don't know where or how to release
Right, you first need to familiarise yourself with the Cocoa Memory Management Rules.
In summary, if you obtain an object by alloc, a method containing "copy", a method starting with "new" or if you retain it, you need to release or autorelease.
Take method1:
-(void)method1{
userInputString = #"something";
}
userInputString was not obtained with alloc, new or copy, nor have you retained it. Therefore you do not own it so you must not release it. If you had done this:
userInputString = [#"foo" copy];
or this:
userInputString = [[NSString alloc] initWithString: #"foo"];
or this:
userInputString = [#"foo" retain];
you do own the string therefore you must release or autorelease it.
When you release it depends on its scope. If it's a local variable, you must release or autorelease it before the block it is declared in exits. If it is an instance variable, you must release it before the object it is in is deallocated. i.e. you must release it in the dealloc method for the object. In all cases, if you overwrite an object you own, you must release it first. So:
userInputString = [someOtherString copy]; // you own userInputString
// do some stuff
[userInputString release]; // you no longer own it
userInputString = [someOtherString retain];// overwrite the pointeer with something else
This is one of the reasons for adding getters and setters for instance variables. Every time you set a new value, you have to release the old value and retain the new value (making sure that the old bvalue and new value are different), so this is encapsulated in the setter. A synthesized property adds this code automatically.
Try to use autorelease pool:
int main()
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
....
// Your code here
[pool drain]
return 0;
}
#"blablabl" is a shorthand to create an autoreleased NSString from a constant string. If if you don't have an autorelease pool in the thread you are running, those NSString object won't ever be released and of course your create a leak.
Either create an autorelease pool as Sumai suggest or release those objet's memory yourself. (tip: create an NSAutorelesePool ;-) )