WEB开发网
开发学院手机开发iPhone 开发 如何避免iPhone应用中内存泄露 阅读

如何避免iPhone应用中内存泄露

 2013-08-22 13:40:16 来源:WEB开发网   
核心提示:[obj release]; } 在这个例子中,output 的所有者是 GetOutput,如何避免iPhone应用中内存泄露(2),让 Test 释放 obj 违反了Coccoa内存管理指南中的规则,尽管它不会泄露内存但是这样做不好,最后 copiedName 释放这个对象,name 成为这个串的唯一所有者,因为
[obj release];
}
在这个例子中,output 的所有者是 GetOutput,让 Test 释放 obj 违反了Coccoa内存管理指南中的规则,尽管它不会泄露内存但是这样做不好,因为Test 不应该释放并非它所拥有的对象。

正确的方法:
- (NSMutableString*) GetOutput
{
NSMutableString* output = [[NSMutableString alloc] initWithString:@"output"];
return [output autorelease];
}
- (void) Test
{
NSMutableString* obj = [self GetOutput];
NSLog(@"count: %d", [obj retainCount]);
}
在第二个例子中,output 被设置为当 GetOutput 返回时自动释放。output的引用值减少,GetObject 释放 output 的所有权。Test 函数现在可以自由的 retain 和 release 对象,请确保它不会泄露内存。
例子中 obj 被设置为自动释放,所以 Test 函数没有它的所有权,但是如果它需要在其他地方存储对象会怎样?
此时对象需要有一个新的所有者来保留。
Setters
setter函数必须保留它所存储的对象,也就是声明所有权。如果我们想要创建一个 setter 函数,我们需要在分配一个新的指向成员变量的指针之前做两件事情。
在函数里:
- (void) setName:(NSString*)newName
首先我们要减少成员变量的引用值:

[name release];
这将允许当引用值为0时 name 对象被释放,但是它也允许对象的其他所有者继续使用对象。
然后我们增加新的 NSString 对象的引用值:
[newName retain];
所以当 setName 结束时, newName 不会被取消分配。 newName 现在指向的对象和 name 指向的对象不同,两者有不同的引用值。
现在我们设置 name 指向 newName 对象:
name = newName;
但是如果 name 和 newName 是同一个对象时怎么办?我们不能在它被释放后保留它,并再次释放。
在释放存储的对象前保留新的对象:
[newName retain];
[name release];
name = newName;
现在两个对象是相同的,先增加它的引用值,然后再减少,从而使得赋值前引用值不变。
另一种做法是使用 objective-c:
声明如下:
@property(nonatomic, retain) NSString *name;
1. nonatomic 表示没有对同一时间获取数据的多个线程进行组块儿。Atomic 为一个单一的线程锁定数据,但因为 atomic 的方式比较缓慢,所以不是必须的情况一般不使用。

2. retain 表示我们想要保留 newName 对象。

我们可以使用 copy 代替 retain:
@property(nonatomic, copy) NSString *name;
这和下面的函数一样:

- (void) setName:(NSString*)newName
{
NSString* copiedName = [newName copy];
[name release];
name = copiedName;
[name retain];
[copiedName release];
}
newName 在这里被复制到 copiedName,现在 copiedName 拥有串的一个副本。name 被释放,而 copiedName 被赋给 name。之后 name 保留这个串,从而使得 copiedName 和 name 同时拥有它。最后 copiedName 释放这个对象,name 成为这个串的唯一所有者。

如果我们有如下的函数,像这样的 setters 将被输入用来保留成员对象:

- (void) Test
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// do something...
name = [self GetOutput];
// do something else...
NSLog(@"Client Name before drain: %@", name);
[pool drain];
NSLog(@"Client Name after drain: %@", name);

上一页  1 2 3 4  下一页

Tags:如何 避免 iPhone

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接