release an object, memory management, Objective C [closed] - iphone

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
If I have
ClassA.h
1.#property (nonatomic, retain) NSMutableArray *arr;
ClassA.m
-(ClassA) function {
1.ClassA *obj = [[ClassA alloc] init];
// initialize the arr
// add another object into the arr
2. [obj.arr addObject:nameOfAnObject]
3. return obj;
}
at ClassB, I want to call (ClassA) function method.What I do is
ClassB.m
-(void)viewDidload {
1.[super viewDidLoad];
2.ClassA *classAinB = [[classA alloc] init];
3.classAinB = [classA function];
4.[classAinB release];
}
According the rule of memory management,because I own a ClassAinB in ClassB.m, so I free it at the end.
My question is how is the var ClassA which I own in ClassA.m, when should I release it so that after a call back at line 3 of ClassB, I still have the object of ClassA whose arr is containing nameOfAnObject object
Please advice me on this issue. Any comments are welcomed here. Thanks

Add it to the autorelease pool. i.e. return [obj autorelease];. This will make sure the object is sent a release message at the end of the run loop iteration if it no longer has any owner.

If you use manual retain-release:
You allocate 2 objects of classA. One - when you directly allocate it from classB function, another - when you calls classA function inside that function. So, when line 3 performs, you destroys link (overwrite classAinB var) on first classA object and this is a memory leak.
If you wish use factory method that returns you an object of classA, make that method static.

Anytime you have an alloc you need a corresponding release to match it.
In XCode 4.2 + with the LLMV compiler (and ARC enabled) you don't have to worry about reference counting, so when you alloc an object, you don't need to worry about calling release, in fact you can't, as the compiler will throw an error.

Related

initializing memory for an NSMutableArray / design pattern / refactoring [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I have a view that displays in a UIPopoverController. Before, it just had properties that were associated with it's view for a single object. So it would be something like
TargetDetailView : NSObject
#property Target *target
- (id)initWithTarget:(Target *)target
Now however, in some situations depending on what level zoom the user is looking at our view, there will be multiple targets in the popover. So I added an NSMutableArray *targets property to the class in order to show multiple targets in the popover.
Right now, the actual target objects that get drawn on our view are getting drawn on top of each other which is a waste.
The initWithTarget method only got called when you actually clicked on a target and the popover got presented.
What I'm trying to do now is calculate ahead of time where I am goign to have multiple targets in the same location, draw it only once, but when pressed have the popover show and this time, use the NSArray *targets to search through to show the multiple targets in that location.
The problem I have is I do not know where to initialize the memory for the NSMutableArray *targets. The TargetDetailView only gets initialized when you press the target, but I want to calculate ahead of time from my other class when the target views are on top of each other to only draw it once.
I sort my targets in order in terms of location, then I look to see if the first two are similar enough in location to bin them:
for (int i = 0; i < [sortedArray count] - 1; i++) {
TargetDetailView *firstTargetDetailView = (TargetDetailView *)[sortedArray objectAtIndex:i];
TargetDetailView *secondTargetDetailView = (TargetDetailView *)[sortedArray objectAtIndex:i + 1];
if (secondTargetDetailView.target.location - firstTargetDetailView.target.location < scale) {
[firstTargetDetailView.targets addObject:secondTargetDetailView.target]; // crash
[newTargetDetailViewArray addObject:(TargetDetailView *)[sortedArray objectAtIndex:i]];
}
}
I try to have the first TargetDetailView.target property point to the next TargetDetailView if it's close enough in location. However, the .targets property never gets initialized since my TargetDetailView only gets initialized on press.
How should I either
a) allocate memory for this object
b) refactor and/or allocate memory for this object
Thanks.
If I may make a suggestion, you could use the same initWithTarget method but always keep your targets in an array. You could then initialize your array there and add your Target parameter from the start, like this:
#interface TargetDetailView :NSObject
#property (nonatomic, retain) NSMutableArray *targets;
- (id)initWithTarget:(Target *)target;
#end
#implementation TargetDetailView
#synthesize targets;
- (id)initWithTarget:(Target *)target {
self = [super init];
if (self) {
targets = [[NSMutableArray alloc] initWithObject:target];
}
return self;
}
You can then use the targets property to add more targets (if you'd like) and use a simple loop through targets without having to care about the number of items in there.

Potential leak of an object allocated on line ##

I am working on an iphone application, and although I thought I had a good understanding of memory management, I'm seeing some issues after using the Xcode Analyze function. I have looked at many of the existing questions I could find on here, but I couldn't find one that was similar to my situation.
CustomerDetailController.h
#interface CustomerDetailController : UITableViewController {
PTCustomer *customer;
}
#property (nonatomic, retain) PTCustomer *customer;
- (id)initWithCustomer:(PTCustomer *)aCustomer;
CustomerDetailController.m
#synthesize customer;
- (id)initWithCustomer:(PTCustomer *)aCustomer {
if ((self = [super initWithStyle:UITableViewStyleGrouped]))
{
if (aCustomer != nil)
self.customer = aCustomer;
else
self.customer = [[PTCustomer alloc] init]; // This line shows Potential leak of an object allocated on line ##
}
return self;
}
If I click on the item marked by the Analyzer, it then says:
Method returns an Objective-C object with a +1 retain count
Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1
My reasoning behind this is that if a PTCustomer object was not passed in, I want to initialize a new one so that I have it available elsewhere within this class.
What is the correct way to do this?
Thanks.
self.customer is being over-retained.
+1 for alloc of customer
+1 when the property setter retains customer.
Do not retain customer, the property setter will retain it.
Just:
self.customer = [[[PTCustomer alloc] init] autorelease];
But given that this is an init method there is a strong argument that the ivar should be assigned directly:
customer = [[PTCustomer alloc] init];
The other option is to assign the retained object directly to customer rather than to self.customer. This bypasses the auto-retain logic in the setCustomer method. However, if you do that you must assure that any prior object referenced by customer is released (eg, by assigning nil to self.customer).
(Because bypassing the setter in this way is a somewhat irregular technique some folks frown on it.)
Are you releasing your customer ivar in the dealloc? If not, there's your leak.

Objective C - Basic question? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Why use 'self.' when its not forced?
What is the difference between these 2 blocks of code?
#property (nonatomic, retain) MyObject *myObject;
MyObject *obj = [[MyObject alloc] init];
self.myObject = obj;
[obj release];
MyObject *obj = [[MyObject alloc] init];
myObject = obj;
[obj release];
EDIT:
Does it mean that on the second block I don't need to release "obj" ?
In the first case, self.myObject implies that myObject is a #property, and when you assign to it with self.myObject = obj, that property's setter will get invoked. Often, that setter is automagically generated by the compiler with the #synthesize directive. If that property's autogenerated setter is flagged with retain, then whatever assigned to it (in this case, obj) will be retained by the property.
In the second case, myObject may or may not be a property. Regardless, this is a simple assignment. No retain is done.
The first one calls the accessor of self, and the second doesn't. A logical equivalent for the first block might be:
MyObject *obj = [[MyObject alloc] init];
[self setMyObject:obj];
[obj release];
As you can see, a method invocation happens there on the second line, which doesn't happen in the second line of your second example.
self is used to access class/instance properties (an accessor). For example, if you defined a property in your header file (using #property), it is good practice (for code readability amongst other things) to use self.myClassProperty. Local variables, like variables declared inside functions (or even outside functions as members), are accessed without the self keyword.
Similar SO Question here: Objective-C - When to use 'self'
that depends on how you have declared myObject in your header file. The prevalent practice in the the boilerplate code makes those to semi equivalent.
the difference is that 1 is guaranteed to be using the property named myObject, and therefore will trigger the getter and setter functions.
the second one accessed the the instance variable and is not guaranteed to use the getter and setter functions. if your ivar has the same name as the property it should use the setter and getter functions.
the way to make this more explicit is to prepend something to all of your ivars. (eg mMyObject) and then use a mutator in #synthesize
#synthesize myObject = mMyObject;

assignment of property and allocation leads to retain count of 2

I had a look at instruments and I saw that the alloc increased the retain count by 1. So far everything clear. But the assignment of the class to my property also increased the retain count to 2.
self.myProperty = [[MyClass alloc] init]
Vs.
MyClass *myCreatedVariable = [[MyClass alloc] init];
self.myProperty = myCreatedVariable
To decrease the retain count to zero I released myCreatedVariable right after my calls. The myProperty instance variable is released in the dealloc method. Am I right that a property only is released in the dealloc method?
Now to my question:
Is the allocation and the assignment to a property always creating a retain count of 2? So don't use
self.myProperty = [[MyClass alloc] init]
because the retain count is never getting zero? Or is this only the case if I'm allocating a class?
Cheers
Your property is most probably declared as retaining or copying:
#property (retain) MyClass myProperty;
or
#property (copy) MyClass myProperty;
This calls your setter that does what its attributes say: retain! Copy will also retain.
Although it worked here, you shouldn't try to get useful information out of the retainCount property.
I cannot recommend the Memory Management Programming Guide highly enough, well worth a first, second and third read. :-)
Creating objects using the init function returns a retained instance by default. ( See the Memory Management Programming Guide)
If the property is defined with the 'retain' attribute, then your object is retained one more time.
So the right way to do is
MyClass *myCreatedVariable = [[MyClass alloc] init];
self.myProperty = myCreatedVariable;
[myCreatedVariable release];
By the way this is good to know also when you using Arrays.
Once an object created with the alloc and init functions is added into an array, it is retained by the array, so you can release your instance after you add it in the array.
In both case, retainCount is then 1, as expected.
if your property is defined with the 'copy' attribute, you can release the object as well, and even kill it, since it has been fully copied and retained once.
( I think there is something there if you use garbage collection instead of managed memory... To check.. )
Finally if your property is set with the 'assign' attribute, only the object's adress is copied, so you should not release your original object in this case.
It is however not recommanded to use the 'assign' attribute, since you may set property with objects that you did not create yourself, and which could be released anytime, letting your property pointing in the fields...
Finally, don't forget that static creators in Cocoa do not return retained objects.
( This is a convention, exceptions may exist... )
example:
NSArray* myArray = [NSArray array];
self.myProperty = myArray;
In this case, do not release myArray, it is already done in the creator function.
Assigning it to the property will retain it.( with retain or copy attribute).
Hope it will help,
Cheers
#property (nonatomic, retain) NSString *strURL;
This will keep the Retain count = 0
When you use an accessor to initialize the strURL then the retain count increases to 1
self.strURL = [NSString stringWithString:#"http://192.168.1.25/shop.php"];
However if you had done this without using the accessor then your reference count would have remain same that is 0
strURL = [NSString stringWithString:#"http://192.168.1.25/shop.php"];
Note that when you use this variable with retain count as 0, the auto release works and the variable gets released, giving "SIGABART" error or “EXC_BAD_ACCESS” when you try to access its value.
Generally when you are using init to get your variables initialized the best practice is to use alloc.
strURL = [[NSString alloc] stringWithString:#"http://192.168.1.25/shop.php"];
Hope this helps!
Sorry ? Noooo. I'm afraid programming is trying to know things we don't know everyday !
Static creators are convenience function, to ease common objects allocations.
A lot of classes in the cocoa framework have this kind of functions. Arrays, Dictionary, Paths, ...
Let's take your class as an example, and suppose you often have to create objects of this class. You may write a function in your 'myClass' implementation like:
+(MyClass*)myClass
{
MyClass *myNewInstance = [[myNewInstance alloc] init];
return [myNewInstance autorelease];
}
Then you can rewrite your original example as:
..
self.myProperty = [MyClass myClass];
..
Straight!
Or you could write a method like
-(void)myFunction
{
MyClass* myTempObject = [MyClass myClass];
if (myTempObject) {
// do something with your temporary object
}
// Simply exit, object will be released later on.
}
It is much shorter ( we should handle the case where object creation failed ) ..
Note that this is all conventions, you can basically do has you like and create retained objects, or use a different name for the creator.
But it is safer to follow the framework rule, it then becomes a reflex when you code.
See methods like [NSDictionary dictionary], [NSArray array], [NSArray arrayWithObjects:] ,...
Cheers

Objective-C Setter Memory Management

Still a little confused about Objective-C memory management. I think my confusion stems from what exactly the autorelease means.
NSString *theBackendResponse = [[NSString alloc] initWithData:receivedData encoding:NSASCIIStringEncoding];
NSDictionary *accountDictionary = [theBackendResponse propertyList];
[viewController setAccountDictionary:accountDictionary];
Now, what should I do with the accountDictionary in the setAccountDictionary method of my view controller? Right now I just set the instance variable "accountDictionary" to whatever is returned. Should I set it to a retained one, and then release the one that's returned? What should my setter code block look like, given that NSString's propertyList method is autoreleased?
By the way, if I release theBackendResponse, will I lose the accountDictionary? I assume not...
Calling [objectInstance autorelease] adds an object to the current NSAutoreleasePool. When that pool receives a drain message, it sends a release to all the objects in the pool. If any of those objects' retainCount reaches 0, they are deallocated at that point. The purpose of autorelease is to allow you to mark an object to be released "some time in the future". This is especially useful for things like methods that return a newly allocated object but want to release it so that the caller doesn't have to take ownership of the returned object. A method might look like this:
- (id)myMethod {
id myObj = [[SomeClass alloc] init];
...
return [myObj autorelease];
}
The caller of myMethod would then retain the return value if they wanted to take ownership of the returned value or ignore it if not. When the current NSAutoreleasePool is drained, myObj will get a release message. If no other objects own it (i.e. have sent it a retain message), it will get deallocated.
All of this is explained in the Cocoa Memory Management Programming Guide. Even if you've already read it, it's always worth an other read.
So, to answer your questions:
First, you should release theBackendResponse. You will leak memory if you do not. You don't need to know what accountDictionary does with the string: if it needs to keep a reference it will have retained theBackendResponse. You have an ownership of theBackendResponse because you alloc'd it, so you must relinquish that ownership (via release or indirectly via autorelease).
Second, you must retain or copy the argument to setAccountDictionary: if you want to keep a reference to that object or value respectively. The standard setter method looks something like this (assuming you do not need atomic semantics):
-(void)setAccountDictionary:(NSDictionary*)newDict {
if(newDict != accountDictionary) {
id tmp = accountDictionary;
accountDictionary = [newDict copy]; //Since newDict may be mutable, we make a copy so that accountDictionary isn't mutated behind our back.
[tmp release];
}
}
You must also remember to release accountDictionary in the dealloc method:
- (void)dealloc {
[accountDictionary release];
[super dealloc];
}
Since you appear to be using NSViewController, I assume you're on Leopard (OS X 10.5) in which case, you should probably be using #property and the #synthesized getter/setter if possible. To do this, add a
#property (copy,readwrite) NSDictionary * accountDictionary;
declaration to the class #interface. And add a #synthesize accountDictionary; directive in the #implementation block for your controller class.
In general, one object or method should not have to care about how another is managing memory. The fact that somebody else has autoreleased something is irrelevant to you. It's simpler to think of the concept of ownership. So retain and some other methods claim ownership, and release and autorelease relinquish it. If an object needs to keep a reference to another, it should claim ownership for as long as it needs. Thus, setter methods usually either retain or copy the new value and release or autorelease the old value.
I strongly recommend reading the Cocoa memory management guidelines. They're not all that long or complicated, and it's very important to understand them.
The set accessor method should always copy / retain the incoming value before releasing the old, in the case where the old value is the only object that owns the new value:
-(void)setAccountDictionary:(NSDictionary*)newDict {
id old = accountDictionary;
accountDictionary = [newDict copy];
[old release];
}
If accountDictionary referred to newDict and the retain count for newDict was 1, the call to [accountDictionary release] before the call to [newDict copy] would cause the retain count to got to 0 and therefore release newDict.
As an example of incorrect code, where we release the old dictionary and then copy the new dictionary:
-(void)setAccountDictionary:(NSDictionary*)newDict {
[accountDictionary release];
accountDictionary = [newDict copy];
}
and have the following code:
NSDictionary *dict = [obj accountDictionary];
[obj setAccountDictionary:dict];
It's contrived, but it demonstrates that in the setter, accountDictionary and newDict refer to the same instance. If the retain count is 1, the [accountDictionary release] line will decrease the retain count to 0, and thus release the instance from memory. [newDict copy] will now refer to an invalid instance.
Apple describes several concepts when implementing accessors: Memory Management Accessor Methods
If you can use Objective-C 2.0, I would go with properties and dot syntax.
Properties are new in Objective-C 2.0 and provide auto accessor generation.
In the .h File:
#property (retain) NSDictionary* accountDictionary;
In the implementation:
#synthesize accountDictionary;
Synthesize generates accessor methods for your NSDictionary. (If you want to provide your own implementation, you could also do that)