显示Plist词典中的随机单词 - 内存泄漏?

时间:2010-01-16 00:13:47

标签: iphone objective-c cocoa dictionary plist

我是iphone开发的新手。我是“老学校” - 在编程时我很想使用程序等。如今,一切都是面向对象的,但我的风格仍然如此。请记住这一点。我的项目很小,实际上只是一个概念证明。

下面的程序适用于计时器 - 每30秒它会从我的应用程序存储在Dictionary.plist中的名字数据库列表中读取一个随机的婴儿名称。然后它会在iPhone屏幕上显示此名称。

您可以在下面看到代码的完整相关部分。 会发生什么 - 如果我增加计时器以非常快地运行 - 最终它似乎耗尽内存或其他东西,因为它只是显示????而不是下一个随机的婴儿名字。 我怀疑这是因为我每次阅读都没有关闭数据库文件。

无论如何,有人可以看看我的代码(考虑到我的上述评论)并告诉我需要添加什么来阻止它显示????经过这么多次运行..

我每次只在ShowNextName中打开文件,因为我无法想出另一种方法来做这件事。

我知道在这个全局等代码的开头使用变量并不是很好的风格但是可能有一种方法可以重新构建或添加一些东西来阻止它“崩溃”或在这么多次运行后变得有点滑稽。 ..

我很感激。感谢。

#import "BabyNameViewController.h"

@implementation BabyNameViewController


NSDictionary *dictionary;
NSString *name;

int nameCount = 0;
int RecordIndex = 0;


- (void)ShowNextname;
{
    NSString *path = [[NSBundle mainBundle] bundlePath];
    NSString *finalPath = [path stringByAppendingPathComponent:@"Dictionary.plist"];
    NSArray* plistArray = [NSArray arrayWithContentsOfFile:finalPath];

    // Generate a random number between 0 and (the number of records-1) - used as a random index!

    RecordIndex=arc4random()%[plistArray count];


    // Select and display currently selected record from the array.
    dictionary = [plistArray objectAtIndex:RecordIndex];
    name = [dictionary objectForKey:@"name"];

    [nameLabelOutlet setText: [NSString stringWithFormat: @"Random Baby Name is: %@", name]];

}   

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];

// Initial App entry point - startup code..


// Open the dictionary to count the number of names and store it for later use.
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *finalPath = [path stringByAppendingPathComponent:@"Dictionary.plist"];
NSArray* plistArray = [NSArray arrayWithContentsOfFile:finalPath];
nameCount = [plistArray count];

// Generate random name from database   
[self ShowNextname];

// Start up the nameUpdate timer.
[NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(nameUpdate) userInfo:nil repeats:YES];

}

-(void) nameUpdate {
    [self ShowNextname];
}

4 个答案:

答案 0 :(得分:1)

问题可能是您每30秒将plist重新加载到一个新阵列中。你应该做的是在viewDidLoad中将plist加载到对象(你的视图控制器类)中的实例变量中,然后在showNextName中使用该实例变量。 (另外,我总是命名以小写字母开头的方法和带大写字母的类,否则人们可能会认为ShowNextname是一个类而不是一个方法。)

另外,请不要忘记在[plistArray release];方法中添加dealloc

这是一篇很好的免费文档,您可能希望阅读它可能对某些人有所帮助:

http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/OOP_ObjC/Introduction/Introduction.html

答案 1 :(得分:1)

你有一个额外的间接层:你可以这样做:

[NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(ShowNextName) userInfo:nil repeats:YES];

并删除nameUpdate方法。

答案 2 :(得分:1)

关于过渡到对象的建议 - 它有助于思考像结构这样的对象,你也可以使用方法。实例变量就像结构中的项一样,你需要一个特定的结构(类实例)来获得正确的值 - self只是一种方法来查看它自己的类中保存的值。因此,视图控制器中的方法都在查看一个类实例,即创建用于显示视图的视图控制器。

考虑内存的方法就是这样,当你分配一个真正像malloc的对象时 - 任何风格的init就像在结构中设置初始值一样(因为malloced内存最初可以是任何东西)。然后在该版本之后释放分配的内存,但仅在没有任何保留调用的情况下。保留分配与计数器一起使用的内存blocvk的标记,并释放计数器的减量 - 当它变为0时,内存消失。这是一个简化的视图,但可以帮助您开始。

答案 3 :(得分:0)

如果您的应用程序不断使用更多内存,请在“仪器”(泄漏模板)下运行它,并查看所有内存的运行位置。然后,深入查看总大小正在增长的类,并查看分配事件发生的位置。然后,您将能够找到您违反the memory management rules的位置。

我在您展示的代码中看不到任何此类违规行为,因此问题必须在其他地方。仪器将帮助您找到它。

This video可能对您有帮助。