简体   繁体   中英

iPhone basic memory management

Is this proper memory management? What I'm wondering is if I am supposed to release after the alloc in -viewDidLoad .

SomeViewController.h

#import <UIKit/UIKit.h>

@interface SomeViewController : UIViewController {
    UIButton *someButton;
    NSString *someString;
}

@property (nonatomic, retain) IBOutlet UIButton *someButton;
@property (nonatomic, copy) NSString *someString;

@end

SomeViewController.m

#import "SomeViewController.h"

@implementation SomeViewController

@synthesize someButton, someString;

- (void)viewDidLoad {
    [super viewDidLoad];
    someButton = [[UIButton alloc] init];
    someString = [[NSString alloc] init];
}

- (void)viewDidUnload {
    self.someButton = nil;
    self.someString = nil;
}

- (void)dealloc {
    [someButton release], self.someButton = nil; 
    [someString release], self.someString = nil;
    [super dealloc];
}

@end

Thanks

Edit: one more thing. If I place a UIButton in IB, do I still need to alloc it?

It's quite a long story which you may find by googling around, and someone may enter here, but to keep it short, here's a few tweaks:

- (void)viewDidLoad {
    [super viewDidLoad];
    self.someButton = [[[UIButton alloc] init] autorelease];
    self.someString = [[[NSString alloc] init] autorelease];
}

Ie use the setters ( self.something = ...; ) and always either release or autorelease any alloc you do. (The logical distinction would be who "owns" the objects; with these tweaks the function gives up ownership and the class gets it.)

edit: no, if you create a button in IB, the button will just be there, allocated and initialized with your styles.

When you call init on an object, the retain count goes to 1. You have two different setter attributes: one is "retain" for your UIButton, and the other is "copy" for your NSString. When you call

self.someButton = someUIButtonObject;

someUIButtonObject gets a retain message and so its retain count goes up to 1. In the case of your original code, calling release in dealloc will release one reference to someUIButtonObject, but it will still have a retain count of 1 and will thus be leaked.

The other case with your NSString has a different problem but still leaks memory. Here your call to [[NSString alloc] init] results in a new string object, and then calling

self.someString = someNSStringObject;

results in the creation of a brand new object which copies the content of someNSStringObject. In this case, someNSStringObject and the setter's copied object each have a retain count of one. Here, you leak the string you alloc init-ed because you no longer have a reference to it and it goes out of scope with a retain count of one.

A quick side note: I don't know what your actual code looks like, but don't forget that NSStrings are immutable (so just calling [[NSString alloc] init] is pretty useless) and UIButton needs a frame (try [[UIButton alloc] initWithFrame:(CGRect)frame];).

Basically you need to match each call to retain, copy, or alloc with a call to release (or autorelease). It is appropriate so use

self.someButton = [[[UIButton alloc] init] autorelease];

Which will release the object, though at some unknown time in the future. Don't use autorelease if your memory is very tight and you need memory ASAP. In that case you would do:

UIButton* tempButton = [[UIButton alloc] init];
self.someButton = tempButton;
[tempButton release];

which guarantees that you don't have large objects waiting around in your autorelease pool.

Also, always use the getters/setters to access these properties (self.someButton as opposed to someButton). That way you don't accidentally assign someButton to a new pointer and leak the old one.

When you create a button in IB, the XIB holds a reference to the button (+1 retain count). If you create an IBOutlet so you can access the button programmatically, you get another retain on the object, so if you have an IBOutlet to someButton, someButton has a retain count of 2 as soon as the XIB is loaded. You do not need to alloc the object, that is done automatically when the XIB is loaded into memory. Also, you are only responsible for releasing one reference to the button (your IBOutlet reference). In general, it is a good practice to release your reference as soon as you know you no longer need it. For example, if you know you need a button and have to do initial customization and nothing else, then you would probably do something like this:

-(void)viewDidLoad {
  // Do some customization of someButton
  [someButton release];
}

Otherwise you would probably release someButton in viewDidUnload since you know at that point you won't need the reference to the button anymore.

If your button is set in IB, you do not need to allocate it in the code (IB does it for you).

Basically, each object you created using alloc or new , should have a release somewhere in your code. If it's an interface variable, you should release them in the dealloc function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM