Releasing synthesized property after alloc init - objective-c

i have a property
//.h
#property (nonatomic, retain) SomeCLass * someSynthInstance;
//.m
#synthesize someSynthInstance = _someSynthInstance;
- (void) foo
{
self.someSynthInstance = [[SomeCLass alloc] init];
//[self.someSynthInstance release]; <- SHOULD I RELEASE HERE???
}
- (void) dealloc
{
self.someSynthInstance = nil;
}
my theory goes, that [alloc, init] creates a count of 1, and the setter, inc that count, so it becomes 2, therefore i should release it, right after
but aim getting exc_bad_access in the application after i changed everything like this, so aim not sure if its ok

you want to be releasing the instance variable rather than the property. so you can do either:
self.someSynthInstance = [[[SomeCLass alloc] init] autorelease]; // puts it in the autoreleasepool so it'll get released automatically at some point in the near future
or
_someSynthInstance = [[SomeCLass alloc] init]; // skip the property
or
self.someSynthInstance = [[SomeCLass alloc] init];
[_someSynthInstance release]; // call release on the instance variable

The standard practice is:
SomeClass *tmpObj = [[SomeClass alloc] init];
self.someSynthInstance = tmpObj;
[tmpObj release];

you should release the class variable instead.. like [_someSynthInstance release]; that should do the trick.

yes you should release after init
SomeCLass *temp = [[SomeCLass alloc] init];
self.someSynthInstance = temp;
[temp release]

Related

Objective-c Array not deallocating objects when removing

// AClass.m
// init
enemyBullets = [[NSMutableArray alloc] initWithCapacity:0];
enemy1 = [[Enemy alloc] initWithBullets:enemyBullets];
// At some point
NSMutableArray *bulletsToDelete = [NSMutableArray array];
for(BulletEnemy *thisBullet in enemyBullets)
{
// If I have to delete
[bulletsToDelete addObject: thisBullet];
}
[enemyBullets removeObjectsInArray:bulletsToDelete];
//dealloc method
[enemyBullets release];
[enemy1 release];
Now Inside Enemy some point in time I do the following:
// Enemy.m
- (id)initWithBullets:(NSMutableArray*) _bullets{
// Enemybullets is a var of Enemy
enemyBullets = _bullets;
}
// At some point...
myBullet = [[BulletEnemy alloc] init];
[enemyBullets addObject:myBullet];
[myBullet release];
The problem is when I do the following at Aclass:
[enemyBullets removeObjectsInArray:bulletsToDelete];
The dealloc method inside BulletEnemy doesn't get called because the retain count isn't 0. Why? But If I release ACLass (which releases enemyBullets) then My bullets get deallocated.
Make Enemy own the enemyBullets. And use reverseObjectEnumerator
// AClass.m
// init
enemy1 = [[Enemy alloc] init];
// At some point
for(BulletEnemy *thisBullet in enemy1.enemyBullets.reverseObjectEnumerator)
{
// If I have to delete
[enemy1.enemyBullets removeObject:thisBullet];
}
//dealloc method
[enemy1 release];
//Enemy.h
#property (retain) NSMutableArray* enemyBullets;
// Enemy.m
#synthesize enemyBullets = _enemyBullets;
- (id)init{
// Enemybullets is a var of Enemy
_enemyBullets = [[NSMutableArray alloc] init];
}
// At some point...
myBullet = [[BulletEnemy alloc] init];
[enemyBullets addObject:myBullet];
[myBullet release];
-(void) dealloc{
[_enemyBullets release];
}
Aparently, I was asigning something with retain propery, which made the object +1 thus not to deallocate. Just changed the propery to assign and it worked.

iOS NSMutableArray Memory Leak

I'm having a bit of trouble with memory leaks in my objective c code. Could anyone take a look and let me know what they think?
NSStringArray.h
#interface NSStringArray : NSObject {
NSMutableArray *realArray;
}
#property (nonatomic, assign) NSMutableArray *realArray;
-(id)init;
-(void)dealloc;
#end
NSStringArray.m
#import "NSStringArray.h"
#implementation NSStringArray
#synthesize realArray;
-(id)init {
self = [super init];
if ( self != nil ) {
realArray = [[[NSMutableArray alloc] init] retain];
}
return self;
}
-(void)dealloc {
[realArray release];
realArray = nil;
[super dealloc];
}
Factory.m
+(NSStringArray *)getFields:(NSString *)line {
//Divides the lines into input fields using "," as the separator.
//Returns the separate fields from a given line. Strips out quotes & carriage returns.
line = [line stringByReplacingOccurrencesOfString:#"\"" withString:#""];
line = [line stringByReplacingOccurrencesOfString:#"\r" withString:#""];
NSStringArray *fields = [[NSStringArray alloc] init];
for (NSString *field in [line componentsSeparatedByString:#","]) {
[fields.realArray addObject:field];
[field release];
}
return [fields autorelease];
}
The Leaks tool is saying that the leak occurs when fields is allocated, and when I am adding field string to the fields array.
Also, this function is getting called each line of a file that I'm parsing.
Any tips would be helpful.
Thanks!
This line does a double retain:
realArray = [[[NSMutableArray alloc] init] retain];
it is enough
realArray = [[NSMutableArray alloc] init];
In this piece of code, you break the memory management rules.
for (NSString *field in [line componentsSeparatedByString:#","]) {
[fields.realArray addObject:field];
[field release];
}
You do not own the object pointed at by field so you must not release it.
You have overreleased field so the last object to release it (the autorelease pool in your case) is releasing an already dealloc'd object.
From the docs:
An allocation message does other important things besides allocating
memory:
It sets the object’s retain count to one (as described in “How Memory
Management Works”).
Therefore, you don't need to retain something that you've just alloc'ed.
Adding to Felz answer above. Use self.realArray when allocating array
self.realArray = [[NSMutableArray alloc] init];
Because you have created a property for the array so it is better to use "self"
You could also take advantage of the properties in objective C to make
more clear and efficient your code:
NSStringArray.h
#interface NSStringArray : NSObject {
}
#property (nonatomic, retain) NSMutableArray *realArray;
#end
NSStringArray.m
#import "NSStringArray.h"
#implementation NSStringArray
#synthesize realArray = _realArray;
-(id)init {
self = [super init];
if (self) {
self.realArray = [NSMutableArray array];
}
return self;
}
-(void)dealloc {
[_realArray release];
[super dealloc];
}
Now, with the modifier retain of the property realArray you can use
[NSMutableArray array] that return an autorelease mutable array.
The retain properties manage the retain/release stuff by themselves.
You don't need to use the realArray = nil; line. You've already deallocated
the property.
Hope this can help.

Big problem with memory between methods

i don't understand this problem:
i've 2 class A and B, in A view i've two Button, ButtonCreate and ButtonAccess.
In B there is this method:
-(NSDictionary *) returnData
{
NSDIctionary *data= [NSDictionary withObjectsAndKeys.....];
return data;
}
In A i've also a property #property(nonatomic, retain) NSDictionary *dictio, and in .m file #synthesize dictio = _dictio.
ButtonCreate IBAction -->
B *secondaryClass = [[B alloc] init];
_dictio = [[secondaryClass returnData] retain];
[B release];
ButtonAccess IBAction -->
NSString *value = [_dati ObjectForKey... ];
Problem: if i push more than once ButtonCreate, in Instruments i see a memory leak, but if i cut off the "retain" in ButtonCreate method, i've a crash when i access data from ButtonAccess.
I really don't understand how can i do...can you help me?
Thanks a lot.
Try this in A, i think it could solve your problem:
ButtonCreate IBAction --> B *secondaryClass = [[B alloc] init];
self.dictio = [secondaryClass returnData];
[B release];
It appear you are trying to release B, rather than the instance of B which you named secondaryClass.
B *secondaryClass = [[B alloc] init];
_dictio = [[secondaryClass returnData] retain];
[B release];
Should it not instead be:
...
[secondaryClass release];
You didn't release the old value of _dictio, and you didn't release secondaryClass
B *secondaryClass = [[B alloc] init];
if (_dictio != nil)
[_dictio release];
_dictio = [[secondaryClass returnData] retain];
[secondaryClass release];
But, since you declared your property as retain, you can just take advantage of the property doing this for you.
B *secondaryClass = [[B alloc] init];
self.dictio = [secondaryClass returnData]; // sends retain to new, release to old
[secondaryClass release];

Using self.objectname causes profiler to report a memory leak

Please help;
Header File
#import <Foundation/Foundation.h>
#interface MyClass : NSObject {
NSMutableString * myString;
}
#property (nonatomic, retain) NSMutableString * myString;
-(id) init;
-(void) dealloc;
#end
Implementation File
#import "MyClass.h"
#implementation MyClass
#synthesize myString;
-(id) init {
if ((self = [super init])) {
self.myString = [[NSMutableString alloc] init];
}
return self;
}
-(void) dealloc {
[super dealloc];
[self.myString release];
}
#end
Usage
MyClass * m = [[MyClass alloc] init];
[m release];
//-- Xcode 4 profiler reports a memory leak here.
However, when the code in implementation file of the class is changed to not use the [self.myString .....] notation, then no memory leak is reported.
So,
-(id) init {
if ((self = [super init])) {
myString = [[NSMutableString alloc] init];
}
return self;
}
}
and
-(void) dealloc {
[super dealloc];
[myString release];
}
works fine. No memory leaks reported.
Any ideas - is it profiler or is it me (be nice)?
Your memory leak is not caused by using your setter. Your memory leak is caused by you not managing your memory correctly!
If you declare the following property
#property (nonatomic, retain) id value;
That means that the compiler generates methods that look something like this (highly simplified):
- (id)value {
return value;
}
- (void)setValue:(id)aValue {
[value autorelease];
value = [aValue retain];
}
When you use dot-notation, self.value = obj is desugared into [self setValue:obj]. Thence, you are actually causing obj to be retained within the setter. If you initially create an owning reference to obj (by using an +alloc without a corresponding -release or -autorelease), you'll have over-retained obj, and it will never be deallocated. Hence, you need to do something like this:
id obj = [[[NSObject alloc] init] autorelease];
self.value = obj;
or
id obj = [[NSObject alloc] init];
self.value = [obj autorelease];
or
id obj = [[NSObject alloc] init];
self.value = obj;
[obj release];
Whatever you do, you need to make sure that when you assert ownership of an object (by retaining it), you also release it.
Setter methods in Objective-C equate to a reatain of the new object and release of the old object. In your case the compiler will generate a setter method for your myString property that looks something like...
- (void)setMyString:(NSMutableString*)aString {
[myString autorelease];
myString = [aString retain];
}
When you invoke self.myString = in your init method this translates to a call to the setter. The setter in turn retains the object you pass to it. Because you've directly alloc'd the NSString it begins life with a retain count of one, you then call the setter and the retain count becomes two.
There's two approaches to fixing the problem, the first would be to add a call to [myString autorelease] after you alloc it. Or secondly switch your init method to directly assign the ivar...
// in your init method...
myString = [[NSMutableString alloc] init];
It's a good idea to avoid setter usage in init methods, not because of retain counts but because the object as a whole is not yet fully initialized.
#property (nonatomic, RETAIN)
you are retaining my friend. You have to release the object twice then because the retain count is 2
here is what you should do in the INIT method:
NSString *str = [[NSString alloc] initWithString:#"Hello World!"];
self.myString = str;
[str release]; // dont leak
Also I do not recommend using self.someProperty in the class itself. Doing so requires 1 extra objc_msgSend() to be done to access your variable and will slow down your application.

Recommend class design in Objective-C

I'm new to Objective-c. For learning purposes I'm trying to build something like a phonebook. So I'll have a class called Person that will have some properties (name, phone, etc).
Right now I'm not preoccupied about persistence. But, I need something to "hold" Person objects. So I thought about create a class called People, but I don't know how to design it, specially the NSMutableArray that will hold the objects.
What I did was:
PERSON.H
#interface Person : NSObject {
NSString *name;
}
#property(readwrite, copy) NSString *name;
#end
PERSON.M
#implementation Person
#synthesize name;
#end
PEOPLE.H
#interface People : NSObject {
NSMutableArray *peopleArray;
}
#property(readwrite, retain) NSMutableArray *peopleArray;
- (void)addPerson:(Person *)objPerson;
#end
PEOPLE.M
#implementation People
#synthesize peopleArray;
- (id)init {
if (![super init]) {
return nil;
}
peopleArray = [[NSMutableArray alloc] retain];
return self;
}
- (void)addPerson:(Person *)objPerson {
[peopleArray addObject:objPerson];
}
PHONEBOOK.M
...
Person *pOne = [[Person alloc] init];
pOne.name =#"JaneDoe";
People *people = [[People alloc] init];
[people addPerson:pOne];
When I try to use this code, I receive an error:_method sent to an uninitialized mutable array object.
So, since I'm a newbie, probably the way that I did isn't the best/correct one. So, how do I do this?
Two things wrong with your initialiser for people. It should look more like this:
- (id)init {
self = [super init]; // always assign the result of [super init] to self.
if (!self) {
return nil;
}
peopleArray = [[NSMutableArray alloc] init]; // use init not retain.
return self;
}
Because you're not calling init on the NSMutableArray when you create your peopleArray. Try calling:
peopleArray = [[NSMutableArray alloc] init];
instead. You need not retain it unless you say for instance, did this:
peopleArray = [[NSMutableArray array] retain];
For reasons why, see the rules for memory management. These rules are very important for any iPhone or Mac developer to understand, and quite frankly, are simple enough that there's no excuse. :)
In People.m you probably meant to write
peopleArray = [[NSMutableArray alloc] init];
instead of
peopleArray = [[NSMutableArray alloc] retain];