-1

I'm sorry for repost. What have really bug me is if property retain should release when:
case 1 : (code below) button is already alloc in init: then add to subview then release it, and by any chance I set the button property in another class (I didn't release in dealloc:) it will leak then?
case 2 : button is already alloc in init: then add to subview then release it, and by any chance I didn't set the any button property in another class (I didn't use the property) (I release it in dealloc) then it will crash.

So what should I do if I want to alloc button in init: and I want to set the property too ?

@interface SomeClass : UIView {
UIButton *_button;
}
@property (nonatomic, retain)UIButton *button;

@implementation SomeClass
@synthesize button = _button;

- (id)init {
   _button = [[UIbutton alloc] initWithFrame:CGRectMake(0.0f,0.0f,100.0f,20.0f)];
   [[_button titleLabel] setFont:BUTTON_FONT];
   [_button setBackgroundImage:[[UIImage imageNamed:@"button_blue.png"] stretchableImageWithLeftCapWidth:20.0f topCapHeight:15.0f] forState:UIControlStateNormal];
   [_button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
   [_button setTitleShadowColor:[UIColor blackColor] forState:UIControlStateNormal];
   [[_button titleLabel] setShadowOffset:CGSizeMake(0.0f, 1.0f)];
   [_button addTarget:self action:@selector(buttonDidTapped:) forControlEvents:UIControlEventTouchUpInside];
   [self addSubView:_button];
   [_button release];
}

- (void)dealloc {
   //[self.button release]; // case 1
   [self.button release]; // case 2
   [super dealloc];
}
@end
Lunayo
  • 538
  • 7
  • 32

6 Answers6

2

So what should I do if I want to alloc button in init: and I want to set the property too ?

Here's how your code should look:

@implementation SomeClass
@synthesize button = _button;

- (id)initWithFrame:(CGRect)frame {
   if ((self = [super initWithFrame:frame])) {
       UIButton *button = [[UIbutton alloc] initWithFrame:CGRectMake(0.0f,0.0f,100.0f,20.0f)];

       // Setup the button here...

       [self addSubView:button];
       self.button = button;
       [button release];
   }
   return self;
}

- (void)dealloc {
   [_button release];
   [super dealloc];
}
@end

Changes I made:

  • initWithFrame: is the designated initializer of the UIView, so that's the init method you've got to override
  • Always check to make sure that your superclass initialized successfully before you setup your class
  • You've got to return self at the end of your init statements. I don't think your code would have compiled as written.
  • You created a property, you should use it. Use a temp variable to do all the setup for your button, then when you're finished with setup, use the property accesssor to set the variable and release your temp variable.
  • Because you only use the property to get/set your button, when it's time to dealloc you can guarantee that the _button iVar will either be valid or nil. Either way calling release on that variable is OK.
zoul
  • 102,279
  • 44
  • 260
  • 354
kubi
  • 48,104
  • 19
  • 94
  • 118
1

I don’t understand what you mean by “using it for read-only”. As declared, the property is read-write both for the class itself and from the outside. But the question can be reasonably answered nevertheless – once your class retains some object, it must release it when it gets deallocated.


P.S. I think you can safely drop the underscore prefix for private variables, it serves no real purpose and makes you write more code. In fact, with modern runtimes you can even drop the instance variable declaration:

@interface Foo : NSObject {}
@property(assign) BOOL bar;
@end

@implementation Foo
@synthesize bar;
@end
zoul
  • 102,279
  • 44
  • 260
  • 354
  • what I mean read only is = getter method. I want to use the property iVar only to use (getter) it in another Class. It cause crash (bad access) if I release it in dealloc: when didn't set the the iVar. – Lunayo May 15 '11 at 07:27
  • This is a follow-on to Lunayo's earlier questions today: http://stackoverflow.com/questions/6006603/memory-management and http://stackoverflow.com/questions/5015291/memory-management-in-objective-c. Looking at those may give you the context for this. – jscs May 15 '11 at 07:32
  • @Josh Caswell Sometimes I got a problem of using property only to get the variable (never use the setter) and use retain on it (@property (retain, nonatomic) ) and i got a crash whenever I try to release it in dealloc: – Lunayo May 15 '11 at 07:43
1

OK, third attempt: The problem is that you are in fact setting the property by assigning to the instance variable. Properties and instance variables are closely tied, when you give the following declaration…

@synthesize button = _button;

…you are saying that the _button instance variable should be used to store the value of the button property. Which means that your code over-releases, since you alloc the button in init (+1), release the button in init (-1) and then release again in dealloc (-1 again).

If you have not yet studied the Cocoa Memory Management Guide, do it. Even if you don’t plan to read any other documentation (which would be a pity), make an exception with this one, it will pay you back plenty.

zoul
  • 102,279
  • 44
  • 260
  • 354
  • But isn't that they said whenever you using retain keyword in property you must release it in dealloc: . If I didn't release it in dealloc: next time if I set the some button object to property button in another class, it will leak? – Lunayo May 15 '11 at 09:07
  • Read the guide, that’s the best advice I can give you. – zoul May 15 '11 at 09:12
  • I have read it the whole time. Still no clue. The question is only Should property retain always need to release in dealloc: even I didn't use it (set object in it)? – Lunayo May 15 '11 at 10:04
  • create button using, + (id)buttonWithType:(UIButtonType)buttonType method and not release it in "init" method. Hope it helps. – Amit Vaghela May 15 '11 at 11:13
  • @Lunayo: Yes, you *always* have to release retained properties in dealloc. “Not using it” is an argument that does not make sense. If you don’t ever store a value in the property, it’s useless. Once you do, you have to release it. Your current code does not work because you over-release the value stored in the `button` property, that’s the core issue. – zoul May 15 '11 at 15:39
  • @Lunayo: Also, if you don't use a property, the value of the backing variable will be nil. Sending a release message to nil is harmless. – kubi May 16 '11 at 11:53
0

sure, You should release it, because you have used retain for it.

0

In your -init method, you have a balanced retain/release call. So you don't need to release it again. But by doing it, you are sacrificing the reliability of the value held by _button. If somewhere down the lane the button is removed from the subviews, the button's retainCount could hit zero and it can be deallocated. Then the value held by _button is garbage. So you should not release _button in -init and rather you should do that in -dealloc.

Now, if you access the property elsewhere (outside this UIView object), you don't need to release it again unless you retain it there.

Deepak Danduprolu
  • 44,595
  • 12
  • 101
  • 105
-2

Try to replace [self.button release]; with [self.button removeFromSuperview];

albianto
  • 4,092
  • 2
  • 36
  • 54