iPad应用程序在从文件读取时没有崩溃日志崩溃

时间:2011-06-24 16:08:31

标签: objective-c ipad uitableview file-io

我的程序的基本结构让用户从UITableView中选择一个项目,该项目对应于存储的文本文件。然后将该文件读入数组和字典,其中数组具有键(我知道我可以从字典本身获取键,这不是我的问题)。

然后将视图更改为UISplitView,其中主视图具有键,详细视图将字典中的项目归因于该键。在这种情况下,它是用户选择答案的一系列“是/否”问题。

我的问题是这样的:当我点击UITableView(第一个屏幕)中的一个单元格时,它工作正常,数据被完美读取,依此类推。当我回到UITableView并再次单击同一个单元格时,程序崩溃了。这是文件中的read-in-file方法:

-(NSArray *)readFromFile:(NSString *)filePath{
    //  NSLog(@"Path was: %@", filePath);
    NSString *file = [[NSString alloc] initWithContentsOfFile:filePath];

    //  NSLog(@"File was: %@", file);
    NSScanner *fileScanner = [[NSScanner alloc] initWithString:file];

    NSString *held;
    NSString *key;
    NSMutableArray *detailStrings;
    NSMutableArray *keys = [[NSMutableArray alloc] init];
    NSMutableDictionary *details = [[NSMutableDictionary alloc] init];
    /**
    This is where the fun stuff happens!
    **/
    while(![fileScanner isAtEnd]){
        //Scan the string into held
        [fileScanner scanUpToString:@"\r" intoString:&held];
        NSLog(@"Inside the while loop");
        // If it is a character, it's one of the Key points, so we do the management necessary
        if ([[NSCharacterSet lowercaseLetterCharacterSet] characterIsMember:[[held lowercaseString] characterAtIndex: 0]]){
            NSArray *checkers = [[NSArray alloc] initWithArray:[held componentsSeparatedByString:@"\t"]];
            NSLog(@"Word at index 2: %@", [checkers objectAtIndex:2]);

            if(detailStrings != nil){
                 [details setObject:detailStrings forKey:key];
                 [detailStrings release];
            }
            NSLog(@"After if statement");
            key = [checkers objectAtIndex:2];
            [keys addObject:(NSString *) key];
            detailStrings = [[NSMutableArray alloc] init];
        }
        else if ([[NSCharacterSet decimalDigitCharacterSet] characterIsMember:[[held lowercaseString] characterAtIndex: 0]]){

            NSArray *checkers = [[NSArray alloc] initWithArray:[held componentsSeparatedByString:@"\t"]];
            NSLog(@"Word at index 1: %@", [checkers objectAtIndex:1]);
            [detailStrings addObject:[checkers objectAtIndex:1]];
        }
     }
     NSLog(@"File has been read in");
     [details setObject:detailStrings forKey:key];
     NSArray *contents = [[NSArray alloc] initWithObjects:(NSMutableArray *) keys, (NSMutableDictionary *) details, nil];

     [detailStrings release];
     return contents;
}

我已确定该程序在

内崩溃
if(detailStrings != nil)

语句。我认为这是因为我错过了一些我本应该做的内存管理,但是不知道它出了什么问题。关于问题的任何想法,或者为什么在不给我日志的情况下崩溃?

3 个答案:

答案 0 :(得分:3)

当您进入detailStrings循环时,

while未初始化。当您在方法中声明NSMutableArray *detailStrings;时,detailStrings不会自动设置为nil。所以当你这样做时

if ( detailStrings != nil ) { .. }

它进入if语句,因为它没有被初始化,所以当你访问detailStrings时它会崩溃。

另一件事是detailStrings如果首先进入循环的else部分,则不会被初始化。那也会导致崩溃。因此,根据您的要求,要么

NSMutableArray *detailStrings = nil;

或在您输入while循环之前对其进行初始化。

答案 1 :(得分:2)

迪帕克说实话。您应首先使用nil初始化detailStrings。

但还有第二个可能的问题:

我建议在发布后设置nil,因为在下一个循环中你可以用nil测试不存在的内存部分。

if(detailStrings != nil){
            [details setObject:detailStrings forKey:key];
            [detailStrings release];
            detailStrings = nil;
}

第三个可能的问题:根据传入的数据,你可能会第一次进入IF语句的第二部分并尝试将addObject添加到非初始化的数组中。

第四个(希望最后):你有“checkers”数组的内存泄漏

答案 2 :(得分:1)

这就是我所看到的:

//read in the file
NSString *file = [[NSString alloc] initWithContentsOfFile:filePath];
//create the scanner
NSScanner *fileScanner = [[NSScanner alloc] initWithString:file];

//declare some uninitialized stuff
NSString *held;
NSString *key;
NSMutableArray *detailStrings;

//initialize some stuff
NSMutableArray *keys = [[NSMutableArray alloc] init];
NSMutableDictionary *details = [[NSMutableDictionary alloc] init];

//begin loop
while(![fileScanner isAtEnd]){
    //scan up to a newline
    [fileScanner scanUpToString:@"\r" intoString:&held];
    //see if you scanned a lowercase string
    if ([[NSCharacterSet lowercaseLetterCharacterSet] characterIsMember:[[held lowercaseString] characterAtIndex: 0]]){
        //make an array
        NSArray *checkers = [[NSArray alloc] initWithArray:[held componentsSeparatedByString:@"\t"]];

        //do a check... against an uninitialized value
        if(detailStrings != nil){
            //set a potentially uninitialized value into an array with an uninitialized key
            [details setObject:detailStrings forKey:key];

在这一点上,你几乎已经被冲洗了。

修复:

  • 正确初始化您的变量
  • 运行静态分析器
  • 阅读内存管理编程指南