iPhone基本内存管理

时间:2010-07-27 14:30:00

标签: iphone objective-c xcode iphone-sdk-3.0 memory-management

这是适当的内存管理吗?我想知道的是,如果release alloc -viewDidLoad之后我应该#import <UIKit/UIKit.h> @interface SomeViewController : UIViewController { UIButton *someButton; NSString *someString; } @property (nonatomic, retain) IBOutlet UIButton *someButton; @property (nonatomic, copy) NSString *someString; @end 。{/ p>

SomeViewController.h

#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

SomeViewController.m

UIButton

由于

编辑:还有一件事。如果我在IB中放置alloc,我还需要{{1}}吗?

3 个答案:

答案 0 :(得分:4)

这是一个很长的故事,你可以通过谷歌搜索找到,有人可能会进入这里,但为了保持简短,这里有一些调整:

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

即。使用setter(self.something = ...;)并始终releaseautorelease任意alloc。 (逻辑上的区别在于谁“拥有”对象;通过这些调整,函数放弃了所有权,而类得到了它。)

编辑:不,如果您在IB中创建了一个按钮,按钮就会在那里,分配并初始化您的样式。

答案 1 :(得分:2)

当你在一个对象上调用init时,保留计数变为1.你有两个不同的setter属性:一个是你的UIButton的“retain”,另一个是你的NSString的“copy”。当你打电话

self.someButton = someUIButtonObject;

someUIButtonObject获取一条保留消息,因此其保留计数最多为1.对于原始代码,在dealloc中调用release将释放一个对someUIButtonObject的引用,但它仍然具有1的保留计数,因此被泄露了。

你的NSString的另一种情况有一个不同的问题,但仍然泄漏内存。在这里调用[[NSString alloc] init]会产生一个新的字符串对象,然后调用

self.someString = someNSStringObject;

导致创建一个复制someNSStringObject内容的全新对象。在这种情况下,someNSStringObject和setter的复制对象每个都有一个保留计数。在这里,你泄漏了你初始化的字符串,因为你不再有对它的引用,并且它超出了保留计数为1的范围。

快速注意:我不知道你的实际代码是什么样的,但是不要忘记NSStrings是不可变的(所以只调用[[NSString alloc] init]是没用的)并且UIButton需要一个框架(尝试[[UIButton alloc] initWithFrame:(CGRect)frame];)。

基本上,您需要匹配每次调用以保留,复制或分配调用释放(或自动释放)。这是合适的,所以使用

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

将在未来的某个未知时间发布该对象。如果您的内存非常紧张并且您需要尽快使用内存,请不要使用自动释放。在这种情况下,你会这样做:

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

可确保您的自动释放池中没有大型对象等待。

此外,始终使用getters / setter来访问这些属性(self.someButton而不是someButton)。这样你就不会意外地将someButton分配给新指针并泄漏旧指针。

在IB中创建按钮时,XIB会保留对按钮的引用(+1保留计数)。如果您创建一个IBOutlet以便以编程方式访问该按钮,则会在该对象上获得另一个保留,因此如果您有一个IBOutlet到someButton,则只要加载XIB,someButton的保留计数为2。您不需要分配对象,这是在XIB加载到内存时自动完成的。此外,您只负责释放对该按钮的一个引用(您的IBOutlet参考)。一般来说,一旦您知道不再需要它,最好立即发布您的参考。例如,如果你知道你需要一个按钮并且必须进行初始定制而没有其他任何东西,那么你可能会做这样的事情:

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

否则你可能会在viewDidUnload中释放someButton,因为你知道那时你不再需要对该按钮的引用了。

答案 2 :(得分:0)

如果您的按钮在IB中设置,则无需在代码中分配(IB会为您执行此操作)。

基本上,您使用allocnew创建的每个对象都应在代码中的某个位置release。如果它是一个接口变量,您应该在dealloc函数中释放它们。