要发布什么

时间:2011-05-25 12:39:01

标签: ios objective-c memory-management

我确实理解内存管理有问题,虽然我以为我知道了。在我从一个plist导入我的数据后,我完全搞砸了我对引用计数的理解(花了一整天的时间来修复它)

我的plist的结构基本上只是:

<dict>
<key>Menue1</key>
<array>
    <dict>
        <key>pic1</key>
        <string>a</string>
        ...and so on...
    </dict>
    <dict>
        <key>pic1</key>
        <string>a</string>
        ...and so on...
    </dict>
    <dict>
        <key>pic1</key>
        <string>a</string>
        ...and so on...
    </dict>
</array>
<key>Menue2</key>
<array>
    <dict>
        <key>pic1</key>
        <string>a</string>
        ...and so on...
    </dict>
    <dict>
        <key>pic</key>
        <string></string>
        <key>text</key>
        <string></string>
    </dict>
</array>
</dict>

在代码中,我通过

访问此内容
//to get the path
path = [[NSBundle mainBundle] pathForResource:@"plistsName" ofType:@"plist"]; 

//to get the root dictionary from path      
NSDictionary *tempdict = [[NSDictionary alloc] initWithContentsOfFile:path]; 
    dict = tempdict;
// [tempdict release]; <-- app crashes when I release this

// to get the Array of dicts inside of the dict "Menue1"
exercises = [dict objectForKey:@"Menue1"]; 

// to get the dictionary containing the detailed informations
exerciseViewContent = [[NSDictionary alloc] initWithDictionary:[exercises objectAtIndex:0]];

我确实理解引用计数的想法(我想是这样),但我显然没有基本数学。

由于@interface我认为引用如下:

dict = 1
exercises = 1
exerciseViewContent = 1

viewDidLoad之后,我在上面做了所有这些事情,我认为它就像是

dict = 1
exercises = 1
exerciseViewContent = 2
tempdict = 1

所以在第一次我认为我必须在exerciseViewContent以及viewDidLoad内释放tempdict,并释放dict, exercise, exerciseViewContent中的所有三个(dealloc) {1}}让所有这些都等于0.在摆弄了一段时间之后,我发现我必须在exerciseViewContent中释放dealloc,而不是exercise或{{1} (我确实将它们的属性设置为保留在接口中并合成它们),但是不需要完全释放dict比我理解的更多,因为我肯定使用了alloc。只是通过摆弄它现在有效(直到现在)。

所以我想知道:

  • 首先:我的记忆管理是否正确?
  • 什么时候是tempdict已发布,因为我从未发布它(或我的应用程序崩溃)?
  • 这是从plist访问dicts和数组的正确方法吗?
  • 我认为dict包含自动释放,但我应该怎么知道呢?是否有包含自动释放的方法列表(或列表不包含,哪些更短)?
  • 我想有一个实际上有效的经验法则,因为“每个alloc或init都需要发布”显然不适合这里。

此外,我是否需要发布“路径”?

也是:

initWithContentsOfFile

和发布一样,因为我显然也没有释放计时器([timer invalidate]; timer = nil; ),虽然我设置它的属性来保留?或者这是因为它是NSTimer,不需要像NSTimer那样被释放?在类引用的哪个位置,我可以看到哪个类型必须被释放,哪个类型没有默认?

  • (来自Xcode模板:)

    NSInteger

如果我将它的属性设置为保留在界面中,我还是要发布“myOutlet”吗?

1 个答案:

答案 0 :(得分:4)

变量dict和tempDict是指向对象的指针,而不是对象本身。所以当你这样做时:

dict = tempDict;

您实际上只为相同的对象设置了别名。向tempDict发送释放也将其发送到dict。这就是你遇到崩溃的原因。您已经发布了一个刚刚分配的对象,因此您不再拥有它。该对象被释放,使dict成为悬空指针。

  

我的记忆管理是否正确?

没有[tempDict release],最多只有一点。当你完成它们之后,你需要释放dict和exerciseViewContent,因为你用alloc获得它们。

  

什么时候是dict发布了,因为我从未发布它(或我的应用程序崩溃)?

正如我上面所说,tempDict指向同一个对象。释放tempDict并释放dict。

  

这是从plist访问dicts和数组的正确方法吗?

没关系,我只需要像这样获得exerciseViewContent:

exerciseViewContent = [exercises objectAtIndex:0];

然后你不需要释放它。

  

假设initWithContentsOfFile包含自动释放,但我该如何知道呢?

不,它没有。重要的一点是,对象是通过alloc获得的,这意味着您拥有它。您应该如何了解它是通过了解C ocoa Memory Management Rules

  

我想有一个实际上有效的经验法则,因为“每个alloc 或init 需要发布”显然不适合这里。

是的,确实合适。你只是误解了这条线的含义:

dict = tempDict;