Сбой приложения iPad без журнала сбоев при чтении из файла - PullRequest
0 голосов
/ 24 июня 2011

В базовой структуре моей программы пользователь выбирает элемент из UITableView, который соответствует сохраненному текстовому файлу. Затем файл считывается в массив и словарь, где у массива есть ключи (я знаю, что могу просто получить ключи из самого словаря, это не мой вопрос).

Представление затем изменяется на UISplitView, где главное представление имеет ключи, а подробное представление содержит элементы в словаре, приписанные этому ключу. В данном случае это серия вопросов «Да / Нет», на которые пользователь выбирает ответ.

Моя проблема заключается в следующем: когда я нажимаю на ячейку в UITableView (первый экран), она работает нормально, данные считываются идеально и так далее. Когда я возвращаюсь к UITableView и снова нажимаю на ту же ячейку, программа вылетает. Вот метод чтения из файла:

-(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 ]

3 голосов
/ 25 июня 2011

detailStrings не инициализируется при входе в цикл while. Когда вы объявляете NSMutableArray *detailStrings; внутри метода, detailStrings не устанавливается автоматически на nil. Итак, когда вы делаете

if ( detailStrings != nil ) { .. }

он входит в оператор if и, поскольку он не инициализирован, он потерпит крах при доступе к detailStrings.

Другое дело, что detailStrings не будет инициализирован, если сначала войдет в часть else цикла. Это также приведет к сбою. Исходя из ваших требований, либо выполните

NSMutableArray *detailStrings = nil;

или инициализируйте его перед входом в цикл while.

2 голосов
/ 25 июня 2011

Дипак сказал правду. Сначала вы должны инициализировать detailStrings с помощью nil.

Но есть и вторая возможная проблема:

Рекомендую также установить nil после освобождения, потому что в следующем цикле вы можете протестировать несуществующую часть памяти с nil.

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

И третья возможная проблема: в зависимости от входящих данных вы можете в первый раз перейти ко второй части инструкции IF и попытаться добавить addObject в неинициализированный массив.

Четвертый (последняя надежда): у вас утечка памяти с массивами "checkers"

1 голос
/ 25 июня 2011

Вот что я вижу:

//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];

На данный момент вы в значительной степени задумались.

Исправление:

  • правильно инициализироватьваши переменные
  • запустите статический анализатор
  • прочитайте руководство по программированию управления памятью
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...