Приложение часто падает в цикле - PullRequest
0 голосов
/ 22 марта 2010

мое приложение часто падает в этом цикле:

for (int a = 0; a <= 20; a++) {
        NSString * foo = [[NSString alloc]initWithString:[[newsStories objectAtIndex:arc4random() % [newsStories count]] objectForKey:@"title"]];
        foo = [foo stringByReplacingOccurrencesOfString:@"’" withString:@""];
        foo = [[foo componentsSeparatedByCharactersInSet:[[NSCharacterSet letterCharacterSet] invertedSet]] componentsJoinedByString:@" "];
        foo = [foo stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
        textView.text = [textView.text stringByAppendingString:[NSString stringWithFormat:@"%@ ", foo]];
    }

Код изменяет NSString из NSDictionary и добавляет его в textView. Иногда это первый сбой во второй раз, используя цикл for. Что я не прав?

Ответы [ 5 ]

2 голосов
/ 22 марта 2010

initWithString: вызывает исключение, если вы передаете ему нулевой аргумент, поэтому, если в вашем элементе словаря newsStories отсутствует заголовок, это вызовет сбой (если вы не перехватите исключение в другом месте).

Попробуйте отделить часть, которая получает заголовок, и убедитесь, что он не равен нулю, прежде чем передавать его в initWithString:

NSString *titleString = [[newsStories objectAtIndex:arc4random() % [newsStories count]] objectForKey:@"title"];

if (!titleString)
    titleString = @"<TITLE IS EMPTY>";

foo = [[[NSString alloc] initWithString: titleString] autorelease];

В качестве альтернативы, если объект заголовка элемента словаря newsStories неэкземпляр NSString, который также может вызвать сбой initWithString:

0 голосов
/ 22 марта 2010

Я предполагаю, что вы работаете в среде с подсчетом ссылок, то есть сборка мусора отключена.

Сначала попробуйте изменить первую строку внутри цикла на:

    NSString * foo = [NSString stringWithString:[[newsStories objectAtIndex:arc4random() % [newsStories count]] objectForKey:@"title"]];

Использование метода класса stringWithString: вместо alloc и initWithString: дает автоматически освобожденную строку NSString вместо строки с retain count = 1. Это должно устранить утечку памяти, упомянутую в комментариях и / или других ответах.

Тем не менее, каждая операция foo = внутри цикла создает еще одну автоматически освобожденную строку NSString, поэтому в каждой итерации цикла вы создаете 3 (вашу версию) или 4 (если вы сделали вышеупомянутое изменение) строки, которые автоматически освобождаются, наращивать по итерациям и создавать проблемы. Из-за этого может быть полезно создать и освободить пул автоматического выпуска в вашем цикле:

for (int a = 0; a <= 20; a++) {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSString * foo = [NSString stringWithString:[[newsStories objectAtIndex:arc4random() % [newsStories count]] objectForKey:@"title"]];
    foo = [foo stringByReplacingOccurrencesOfString:@"’" withString:@""];
    foo = [[foo componentsSeparatedByCharactersInSet:[[NSCharacterSet letterCharacterSet] invertedSet]] componentsJoinedByString:@" "];
    foo = [foo stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    textView.text = [textView.text stringByAppendingString:[NSString stringWithFormat:@"%@ ", foo]];
    [pool release];
}
0 голосов
/ 22 марта 2010

На самом деле, объявление NSString в цикле не имеет значения, и это хорошо для управления объектом в области цикла.Я обнаружил, что в вашем коде произошла утечка памяти, и после создания nsstring больше не выпускался.Итак, во-первых, вы должны контролировать объект nsstring и убедиться, что нет утечки памяти, после того, как вы ее выделите, вы должны были ее освободить.Во-вторых, я не уверен, что в вашем массиве с именем "newsStories", не могли бы вы загрузить код, чтобы показать некоторые подробности об этом массиве?Например, номер счета этого массива или элементов в массиве.

0 голосов
/ 22 марта 2010

Почему вы используете NSString? Это неизменный класс, который означает, что вы не можете изменить его, и все же вы меняете его несколько раз. Попробуйте использовать NSMutableString.

0 голосов
/ 22 марта 2010

Попробуйте объявить NSString * foo перед циклом. Примерно так:

NSString *foo;
for(int a = 0; a <= 20; a++)
{
foo = [NSString stringWithString:[some code here]];
.
.
.
[do something to foo]
}

Я пару раз сталкивался с ошибками, когда этого не делал.

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