1
.h

@ interface MyClass : NSObject {
   UILabel *mTextLabel;
}

@property (nonatomic, retain) UILabel *mTextLabel;

and Declare @synthesize mTextLabel in the MyClass.m;

and release the object like this.

[self setMTextLabel:nil];
[mTextLabel release];
NSLog (@"%d",[mTextLabel retainCount]);

This result is 0. and I have not found any error or interrupt.

But. When I release mTextLabel like this. I have just got EXC_BAD_ACCESS

[mTextLabel release];
[self setMTextLabel:nil];

I don't understand why it happen. Plz help me.

Beomseok
  • 471
  • 1
  • 6
  • 22

3 Answers3

6

When you have a synthesized property with the retain attribute, the synthesized setter calls release on the old ivar before it sets the new value.

Here is an expanded view of what is happening in the first example:

[mTextLabel release];
mTextLabel = nil;
[mTextLabel release];

Since calling a method on a nil pointer does nothing, there is no problem.

In the second example, here is what is happening:

[mTextLabel release];
[mTextLabel release];
mTextLabel =  nil;

See the problem?

Edit: it is also worth noting that inspecting the retain count of an object is rarely useful, as any number of Cocoa classes may retain it for their own purposes. You just need to be sure that every time you call retain, alloc, copy or new on an object, there is a matching release or autorelease somewhere in your code.

Simon Goldeen
  • 9,080
  • 3
  • 36
  • 45
1

The problem is you are calling release then you are setting the property to nil which also sends a release to mTextLabel before setting it to nil. This is what happens when the property is defined as copy or retain. All you need is the following code.

[mTextLabel release];
mTextLabel = nil;

Edit:

I would like to add that in your code outside of init and dealloc it is completely fine to call self.mTextLabel = nil to properly release if necessary and nil the value of the property. It is however recommended to NOT use the property in the init/dealloc calls. In those cases you will want to create / release the objects directly to avoid the side effects of the accessor.

Community
  • 1
  • 1
Joe
  • 56,979
  • 9
  • 128
  • 135
  • Better, use `self.mTextLabel = nil` and let the property accessor take care of releasing as appropriate. – Simon Whitaker Apr 05 '11 at 20:47
  • I can update the answer but that is somewhat of a preference. – Joe Apr 05 '11 at 20:49
  • @Simon Whitaker read here for example http://stackoverflow.com/questions/4124049/dealloc-use-release-or-set-to-nil-for-properties I would not recommend down voting because of your own best practices. – Joe Apr 05 '11 at 20:52
0

The value is already released when you do [self setMTextLabel:nil]. You don't need to release the value explicitly (unless you created the value using an init or copy method, in which case you should release it as soon as you've assigned to self.mTextLabel).

Note that retainCount has a return type of NSUInteger, so cannot ever be negative. So checking to make sure the retain count is zero and not -1 doesn't work.

Simon Whitaker
  • 20,506
  • 4
  • 62
  • 79