Jas*_*son 3 iphone cocoa memory-leaks objective-c cs193p
我有一个表视图,加载时创建一个人对象
Person.h
#import <UIKit/UIKit.h>
#import "TwitterHelper.h"
@interface Person : NSObject {
NSDictionary *userInfo;
NSURL *image;
NSString *userName;
NSString *displayName;
NSArray *updates;
}
/*
@property (retain) NSString *userName;
@property (retain) NSString *displayName;
@property (retain) NSDictionary *userInfo;
*/
@property (nonatomic, copy) NSURL *image;
@property (retain) NSArray *updates;
- (id)initWithUserName:userName;
@end
Run Code Online (Sandbox Code Playgroud)
Person.m
#import "Person.h"
@implementation Person
/*
@synthesize userName;
@synthesize displayName;
@synthesize userInfo;
*/
@synthesize image;
@synthesize updates;
- (id)initWithUserName:(NSString *)user{
userName = user;
userInfo = [TwitterHelper fetchInfoForUsername:user];
displayName = [userInfo valueForKey:@"name"];
image = [NSURL URLWithString:[userInfo valueForKey:@"profile_image_url"]];
updates = [TwitterHelper fetchTimelineForUsername:userName];
return self;
}
- (void)dealloc
{
/*
[userName release];
[displayName release];
[updates release];
[userInfo release];
[image release];
*/
[super dealloc];
}
@end
Run Code Online (Sandbox Code Playgroud)
在我的UITableView方法内部cellAtRowForIndexPath我正在创建每个人对象并像这样分配图像属性...
Person *person = [[Person alloc] initWithUserName:userName];
NSData *data = [[NSData alloc] initWithContentsOfURL:person.image];
[data release];
Run Code Online (Sandbox Code Playgroud)
当我在Instruments中运行它时,它会突出显示NSData*数据...行,说明泄漏的位置.
它为什么泄漏?
首先,您需要了解实例变量和属性与getter/setter之间的区别.
您可以使用getter/setter(使用点语法self.userName)显式地(例如[self userName])或(等效地)访问属性.请注意,这两个符号完全相同.在对象的接口中使用@property声明一个属性(即,声明对象的接口),如:
@property (copy) NSString* userName;
Run Code Online (Sandbox Code Playgroud)
这个声明基本上等同于输入:
- (NSString*) userName;
- (void) setUserName: (NSString*) theUserName;
Run Code Online (Sandbox Code Playgroud)
您可以通过使用@synthesize(它只是告诉编译器为您编写getter/setter)或自己实现它来实现一个属性(即,您为userName和setUserName编写方法实现).还有一个很少使用的第三个选项@dynamic,它告诉编译器你将在运行时处理这些方法,基本上只是为了获得你可能得到的警告.
接下来,您需要阅读并理解内存管理规则.它只有9个短段,现在就读它,我会等.完成了吗?好.
此外,您需要知道不应在init或dealloc例程中使用getter/setter.
所以你的init例程应该是这样的:
- (id)initWithUserName:(NSString *)user{
userName = [user copy];
userInfo = [[TwitterHelper fetchInfoForUsername:user] retain];
displayName = [[userInfo valueForKey:@"name"] copy];
image = [[NSURL URLWithString:[userInfo valueForKey:@"profile_image_url"]] copy];
updates = [[TwitterHelper fetchTimelineForUsername:userName] retain];
return self;
}
Run Code Online (Sandbox Code Playgroud)
请注意,您使用保留或复制获取存储在ivar中的每个值的所有权.通常,您使用NSString的副本将NSMutableStrings转换为您拥有的NSStrings,而不是保留哪个会使您保留对可能可变字符串的引用.同样的问题适用于NSArray/NSDictionary,但我们假设TwitterHelper打算交出提取的数据.
你的dealloc必须释放各种ivars:
- (void)dealloc
{
[userName release];
[displayName release];
[updates release];
[userInfo release];
[image release];
[super dealloc];
}
Run Code Online (Sandbox Code Playgroud)
您可以使用self.userName访问或更改属性,而不是直接访问ivars.
请注意,您可能根本不考虑存储displayName(以及类似的图像),而只是实现一个从userInfo检索它的属性getter.为此,请删除displayName ivar,将属性更改为:
@property(readonly)NSString*displayName;
删除@synthesize displayName,并添加一个手动getter:
- (NSString*) displayName
{
return [userInfo valueForKey:@"name"];
}
Run Code Online (Sandbox Code Playgroud)
并删除dealloc中的版本.
请注意,您不需要保留/释放displayName中的值 - 您返回接收者不拥有的值,如果他们想要保留它,则由他们复制/保留它.
归档时间: |
|
查看次数: |
944 次 |
最近记录: |