If I am having a variable defined with "Assign" property then is it ok to setting them to nil in dealloc method?
#property (nonatomic, assign) id test;
- (void)dealloc {
self.test = nil;
}
It's better to release the ivar directly. If a subclass overrides the setter methods of a property, your object might leak because your setter is not called. Consider:
#interface ClassA
#property (readwrite, retain) id anObject;
#end
#interface ClassB : ClassA
#end
#implementation ClassA
#synthesize anObject;
- (void)dealloc {
self.anObject = nil;
[super dealloc];
}
#end
#implementation ClassB
- (void)setAnObject: (id)anObject {
// do nothing!
}
#end
Instances of ClassB will leak anObject!
Depends how you do it, if you do it via the property setter (not recommended), then yes.
If you do direct assignment, then no, because the retained object will leak.
So this is fine:
- (void) dealloc {
self.test = nil;
[super dealloc];
}
But this is a no-go:
- (void) dealloc {
test = nil;
[super dealloc];
}
My advice is to just send the release message to all of your retained ivars in -dealloc, this will work nicely because if test happens to be nil, then nothing will happen.
Trust me. Send release directly in -dealloc. That is all.
- (void) dealloc {
[test release];
[super dealloc];
}
Related
Lets assume I have a class ClassA
header:
#interface ClassA : NSObject
- (id)initWithDelegate:(id)delegate;
#end
implementation:
#interface ClassA ()
{
NSObject *_delegate;
}
#end
#implementation
- (id)initWithDelegate:(id)delegate
{
self = [super init];
if( self )
{
_delegate = delegate;
}
return self;
}
#end
Since I skipped the #property definition my delegate declaration defaults to strong? So this code is wrong because it will cause a leak, or does my delagate declaration default to weak?
You do have to qualify that ivar as __weak. The default for an ivar is strong.
Otherwise, as you already know, you risk a retain cycle with delegates.
BTW, the convention here is 'id' rather than NSObject *.
It’s best to write the code in a way that makes this explicit:
#interface ClassA : NSObject
#property(weak) id delegate; // or #property(weak, readonly)
#end
#implementation ClassA
- (id)initWithDelegate: (id) delegate
{
self = [super init];
_delegate = delegate;
return self;
}
#end
By default, you instance variable would be strong.
You are correct, this will cause ARC to retain the _delegate, ie make a "strong" reference. If you want to create a weak reference without declaring a #property, you can use
#interface ClassA ()
{
__weak id _delegate;
}
#end
For some reason I can't use arc, so in my code below..
Foo.h
#interface Foo : NSObject
#property (nonatomic, copy) NSString * string;
#end
Foo.m
#implementation Foo
#synthesize string=_string;
- (void) bar {
self.string = [NSString stringWithFormat:#"test1"];
self.string = [NSString stringWithFormat:#"test2"];
}
-(void) dealloc
{
[_string release];
[super dealloc];
}
#end
The bar method might not always be called, or they can be called multitime.
Is only one release in the dealloc is all needed?
Yes, since you are using properties so setter method will take care of releasing memory allocation.It will allocate memory as follows:
-(void)setValue:(NSString *)strValue
{
if(string)
{
[string release];
string = nil;
}
string = [strValue copy];
}
Is only one release in the dealloc is all needed?
Yes.
Explanation: the setter method releases the old object that was assigned to the property and retains the new one.
I have an array for IBOutlet collection
.h
#interface UpisiRezultat : UIViewController {
NSArray *buttons;
}
#property (nonatomic, retain) IBOutletCollection(UIButton) NSArray *buttons;
.m
#synthesize buttons;
- (void)viewDidLoad
{
[self setValue:[UIFont fontWithName:#"NeverSayNever" size:22] forKeyPath:#"buttons.font"];
[super viewDidLoad];
}
- (void)viewDidUnload
{
buttons = nil;
}
- (void)dealloc
{
[buttons release]; --> Error
[super dealloc];
}
Why does my program crash when I have [buttons release]; in dealloc?
Without it, it doesn't crash...
updated(Dec1) code and Tested.
- (void)dealloc {
self.buttons = nil;
[super dealloc];
}
you should not release them.
http://www.bobmccune.com/2011/01/31/using-ios-4s-iboutletcollection/
If you have made a connection to your buttons with Interface Builder, it's your view that owns it and will release it.
Since buttons is an NSArray and it is explicitly retained, then it must be released and then set to nil in -dealloc.
See Darren's answer at: Settings IBOutlets to nil in dealloc
See an IBOutletCollection example at: http://www.bobmccune.com/2011/01/31/using-ios-4s-iboutletcollection/.
Hey all. Ive got a headache trying to get my head around this. I have a retained property of type NSNumber. When I use this property I instantiate it with an autoreleased NSNumber. When dealloc is called I then get bad access telling me that Im releasing something that has already been released. Heres some code.
#interface RadarAnnotation : NSObject <MKAnnotation> {
}
#property (retain, nonatomic) NSNumber *latitude;
#end
#implementation RadarAnnotation
#synthesize latitude;
- (CLLocationCoordinate2D)coordinate
{
coordinate.latitude = [self.latitude doubleValue];
return coordinate;
}
-(void) dealloc {
[super dealloc];
[latitude release];//error is here when mapViewController is popped off stack.
}
Here is how I instantiate the property in my mapViewController :
poi.latitude = [NSNumber numberWithDouble:map.centerCoordinate.latitude];
What am I doing wrong? Many thanks. Jules.
You should be calling [super dealloc] at the end of the dealloc method.
Person.h
#import
#interface Person : NSObject {
NSString *name;
int age;
Person *spouse;
}
#property (nonatomic, retain) NSString* name;
#property int age;
#property (nonatomic, retain) Person *spouse;
- (id) initWithName:(NSString *)n age:(int)a;
- (id) initWithName:(NSString *)n age:(int)a spouse:(Person*)s;
#end
Person.m
#implementation Person
#synthesize name;
#synthesize age;
#synthesize spouse;
-(id) initWithName:(NSString *)n age:(int)a
{
return [self initWithName:n age:a spouse:nil];
}
-(id) initWithName:(NSString *)n age:(int)a spouse:(Person *)s
{
if((self = [super init]))
{
self.name = n;
self.age = a;
self.spouse = s;
}
return self;
}
-(NSString *)description
{
return [NSString stringWithFormat:#"name=%#, age=%d, spouse=%#", self.name, self.age, self.spouse.name];
}
- (void) dealloc
{
[name release];
[spouse release];
[super dealloc];
}
#end
Then I have code like this
Person *person1 = [[Person alloc] initWithName:#"Matt" age:33];
Person *person2 = [[Person alloc] initWithName:#"Clair" age:29 spouse:person1];
person1.spouse = person2;
NSLog(#"%#", person1);
NSLog(#"%#", person2);
NSLog(#"person1.retainCount=%d, person2.retainCount=%d", person1.retainCount, person2.retainCount);
[person2 release];
NSLog(#"person1.retainCount=%d, person2.retainCount=%d", person1.retainCount, person2.retainCount);
[person1 release];
NSLog(#"person1.retainCount=%d, person2.retainCount=%d", person1.retainCount, person2.retainCount);
At last, person1.retainCount=1 person2.retainCount=1, they never get -(void) dealloc, so when this situation comes up, how to deal with...
What you have here is called a retain cycle and it is the biggest flaw with a reference counting memory management scheme. This is why the convention that delegates are not retained exists.
You need to find a way to either break the cycle (e.g. before releasing a person, set their spouse to nil, and possibly their spouse's spouse) or avoid it altogether. You could, for instance, create a marriage class with two assign properties, one for each partner, and instead of a spouse property, each person has a retain marriage property pointing to the marriage object. Then when a person is deallocated (and it will be now), you set the marriage property for the other partner to nil.
So your interfaces will look something like this:
#interface Person
// ...
#property (retain) Marriage* marriage;
#property (readonly, retain) Person* partner;
#end
#interface Marriage
/*
* DOES NOT RETAIN THE TWO PASSED IN PEOPLE
*/
-(id) initWithPartner: (Person*) aPerson andSpouse: (Person*) anotherPerson;
/*
* Returns the other person in the marriage or nil if the passed in person is not in
* this marriage
*/
-(Person*) partnerOf: (Person*) aPerson;
/*
* Removes a person from a marriage.
*/
-(void) removePartner: (Person*) aPerson;
#end
Person's dealloc would look something like this.
-(void) dealloc
{
Person* thePartner = [self partner];
/*
* Remove both partners from the marriage so that if something else has retained it, there will not be a problem
* with dangling pointers
*/
[[self marriage] removePartner: thePartner];
[[self marriage] removePartner: self];
[[self partner] setMarriage: nil]; // anulls the marriage
[self setMarriage: nil]; // Assuming only self and our partner owned the marriage, it will now be gone
[super dealloc];
}
Person's partner property is implemented thus:
-(Person*) partner
{
return [[self marriage] partnerOf: self];
}
You could also do it the other way around so that the marriage owns the people and the people have a weak reference to the marriage.