objective-c - plist 文件加载的 NSDictionary 内存泄漏

标签 objective-c iphone cocoa-touch memory-leaks nsdictionary

我有一个内存泄漏问题,我无法理解!观看这个初始化方法:

- (id)initWithNomeCompositore:(NSString *)nomeCompositore nomeOpera:(NSString *)nomeOpera {

if (self = [super init]) {

    NSString *pathOpere = [[NSBundle mainBundle] pathForResource:kNomeFilePlistOpere ofType:kTipoFilePlist];
    NSDictionary *dicOpera = [NSDictionary dictionaryWithDictionary:
                                [[[NSDictionary dictionaryWithContentsOfFile:pathOpere]
                                objectForKey:nomeCompositore]
                                objectForKey:nomeOpera]];

    self.nomeCompleto = [[NSString alloc] initWithString:nomeOpera];
    self.compositore = [[NSString alloc] initWithString:nomeCompositore];
    self.tipologia = [[NSString alloc] initWithString:[dicOpera objectForKey:kKeyTipologia]];
}

return self;}

然后这个小变化(注意 self.tipologia):

- (id)initWithNomeCompositore:(NSString *)nomeCompositore nomeOpera:(NSString *)nomeOpera {

if (self = [super init]) {

    NSString *pathOpere = [[NSBundle mainBundle] pathForResource:kNomeFilePlistOpere ofType:kTipoFilePlist];
    NSDictionary *dicOpera = [NSDictionary dictionaryWithDictionary:
                                [[[NSDictionary dictionaryWithContentsOfFile:pathOpere]
                                objectForKey:nomeCompositore]
                                objectForKey:nomeOpera]];

    self.nomeCompleto = [[NSString alloc] initWithString:nomeOpera];
    self.compositore = [[NSString alloc] initWithString:nomeCompositore];
    self.tipologia = [[NSString alloc] initWithString:@"Test"];
}

return self;}

第一个变体会产生内存泄漏,第二个则不会!我就是不明白为什么! Instruments 证明了内存泄漏,突出显示了这一行:

[NSDictionary dictionaryWithContentsOfFile:pathOpere]

这是dealloc方法:

- (void)dealloc {
[tipologia release];
[compositore release];
[nomeCompleto release];
[super dealloc];}

最佳答案

请记住alloc返回您拥有的对象。

如果您将三个字符串属性声明为 retain ,将这些对象分配给您的属性意味着您现在拥有每个对象两次 - 一次是因为您分配了它,另一次是因为您将它分配给了您的属性。这些对象仍然存在,因为没有任何东西释放它们的第二所有权。

如果您将属性声明为 copy (这是声明 NSString 属性的正确方法),分配对象并将副本存储为属性的值。您无需对原始对象进行任何进一步操作,这些对象仍然存在,因为没有任何东西释放它们。

无论哪种方式,这都是你的泄漏。

该属性应声明为 copy ;如果已经存在,请不要尝试通过更改来修复泄漏。

您不应在此处使用属性访问。请记住,分配给属性是 set<PropertyName>:消息,并且您的对象尚未完全初始化。向未完全初始化或未完全释放的对象发送消息会带来麻烦,特别是在涉及子类时,因为它们可能会以父类(super class)不希望的方式重写访问器方法。

所以,在 init只是,直接分配给实例变量。在 dealloc仅限,发送release消息直接发送到实例变量中的对象。在其他地方,请使用属性访问。

您也不应该使用allocinitWithString:这里。它会起作用,但惯例是发送 copy向您已有的对象发送消息,与属性相同。发送copy消息到您的输入字符串对象,然后将副本分配给您的实例变量。

当您确实使用属性访问时,请使用便捷构造函数(例如 stringWith…: ),因为这些返回的对象不属于您。当您将这些对象分配给您的copy时-声明的属性,您实际上将存储您拥有的副本。

另一种方法是使用 allocinitWithWhatever: ,然后立即autorelease在将该对象分配给属性之前;这种方式会创建一个您拥有的对象,然后立即放弃所有权,然后再将其分配给属性。

关于objective-c - plist 文件加载的 NSDictionary 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2887736/

相关文章:

ios - 优化工作流程以更新内部拥有的 cocoapods 依赖项?

cocoa-touch - 如何从基于导航的 iPhone 应用程序中删除导航栏?

ios - 迪尔德 : Library not loaded error in Swift - IQKeyboardManagerSwift

iPhone 应用程序开发 - 将一个 View 加载到另一个 View 中

xcode - 将 SQLite3 数据库逆向工程到 coredata

ios - iOS SDK 中的 MDM iPCU 配置文件安装失败

ios - 如何从 H 文件访问变量

objective-c - 使用 NSUserDefault 在多个进程之间共享数据

ios - 从 NSMutableDictionary 获取 objectAtIndex

iphone - 使用UIView convertRect方法多次检测CGRectIntersectsRect的高级方法