В документации не указывается, если initWithArray: отправляет объекты в старом массиве (prefs) дополнительное сохранение при добавлении в новый массив (userAdded). Должно быть, потому что элементы добавляются в новый массив. Возможно, когда старый массив (prefs) освобождается, количество сохраняемых элементов в userAdded становится слишком низким, объекты также освобождаются, и приложение вылетает. Чтобы проверить это, я запросил содержимое первого массива для подсчета хранения до и после вызова initWithArray:.
NSUserDefaults *myDefault = [NSUserDefaults standardUserDefaults];
NSArray *prefs = [myDefault arrayForKey:@"addedPrefs"];
NSUInteger i, count = [prefs count];
for (i = 0; i < count; i++) {
NSObject * obj = [prefs objectAtIndex:i];
NSLog(@"Object: %@, Retain count: %d.", obj, [obj retainCount]);
}
userAdded = [[NSMutableArray alloc] initWithArray:prefs];
for (i = 0; i < count; i++) {
NSObject * obj = [prefs objectAtIndex:i];
NSLog(@"Object: %@, Retain count: %d.", obj, [obj retainCount]);
}
Объекты сообщают об увеличении количества сохраняемых данных, поэтому массив prefs может быть освобожден без влияния на новый массив. Но при запуске этого кода все еще происходит утечка NSArray.
Так что проблема должна лежать в массиве prefs. Поскольку метод NSUserDelfaults arrayForKey: создает массив prefs, а слова «alloc», «new» или «copy» не встречаются в имени этого метода, вызывающему методу не принадлежит массив prefs. Скорее всего, массив prefs был добавлен в пул авто-релиза. Чтобы проверить эту идею, я окружил приведенный выше тестовый код вызовами NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
и [pool drain]
. Запуск этого кода не приводит к утечке массива.
Так что я думаю, что массив prefs добавляется в пул автоматического выпуска, который не истощается. Самый простой способ устранить эту утечку - создать пул автоматического выпуска перед созданием массива prefs и очистить этот пул по окончании работы с массивом prefs.