#iphone #objective-c #core-data #memory-leaks
#iPhone #objective-c #core-данные #утечки памяти
Вопрос:
У меня есть два UITableViewControllers. Я нажимаю на второй и вызываю следующий метод в viewDidLoad.
Во второй раз, когда я удаляю это представление и возвращаюсь к первому представлению, я получаю утечку памяти.
Инструменты говорят, что проблема в последней строке следующего метода.
- (void)fetchRecords {
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:@"Articulation" inManagedObjectContext:[self managedObjectContext]]];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"articulationGroup == %@", selectedArticulationGroup];
[request setPredicate:predicate];
static NSArray *sortDescriptors = nil;
if (!sortDescriptors)
sortDescriptors = [[NSArray alloc] initWithObject:[[[NSSortDescriptor alloc] initWithKey:@"text" ascending:NO] autorelease]];
[request setSortDescriptors:sortDescriptors];
NSError *error = nil;
NSArray *fetchResults = [managedObjectContext executeFetchRequest:request error:amp;error];
if (!fetchResults)
NSLog(@"no fetch results ArticulationsViewController, error %@", error);
[request release];
self.articulationsArray = [NSMutableArray arrayWithArray:fetchResults];
}
Понятия не имею … ложусь спать :'(
Ответ №1:
Во-первых, вы теряете свой массив sortDescriptors, если используете ветку распределения. <мыльница> Я настоятельно рекомендую вам использовать фигурные скобки вокруг всех блоков if / else, даже если в них всего одна строка — эти ошибки очень сложно обнаружить после факта</soapbox>
Пожалуйста, опубликуйте свой метод dealloc и объявления ivar.
Комментарии:
1. Я подумал то же самое, но sortDescriptors на самом деле статичен и, как ожидается, будет жить дальше.
2. Должен ли он выпускать статические sortDescriptors? Я бы подумал, что их нужно сохранить.
3. Вы оба правы; я не думаю, что sortDescriptors нужно выпускать. Что касается остального, нам нужно будет просмотреть другие соответствующие части кода, чтобы понять причину утечки.
Ответ №2:
Ну, я замечаю две вещи, которые могут быть правильными, но я все равно хотел спросить.
Прежде всего, вы спрашиваете в операторе if: if (!fetchResults)
. Это означало бы, fetchResults
что, возможно, не существует. Тем не менее, вы пытаетесь инициализировать массив с помощью этого.
Во-вторых, я не знаю, как вы распределили articulationsArray
, но имеет ли изменение строки на self.articulationsArray = [[NSMutableArray alloc] initWithArray:fetchResults]]
какой-либо эффект?
Комментарии:
1. self.articulationsArray = [[NSMutableArray alloc] initWithArray:fetchResults], скорее всего, создаст другую утечку, если articulationsArray является сохраненным свойством.
Ответ №3:
Почему ваш sortDescriptors
массив статичен? Обычно вы бы сделали что-то вроде этого:
NSSortDescriptor *textSort = [[NSSortDescriptor alloc] initWithKey:@"text" ascending:NO];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:textSort]];
[textSort release];
Кроме того, после if (!fetchResults)
вам не следует сохранять свой массив, но сделайте что-то вроде этого:
if (!fetchResults)
{
NSLog(@"no fetch results ArticulationsViewController, error %@", error);
}
else
{
NSMutableArray *articulationsArray_tmp = [fetchResults mutableCopy];
self.articulationsArray = articulationsArray_tmp;
[articulationsArray_tmp release];
}
[request release];
Также обратите внимание, как вы могли бы установить articulationsArray
по-другому. Всегда следует быть осторожным с этими NSMutableArray
s … 🙂
Ответ №4:
Этот блок совершенно не нужен и он опасен:
static NSArray *sortDescriptors = nil;
if (!sortDescriptors)
sortDescriptors = [[NSArray alloc] initWithObject:[[[NSSortDescriptor alloc] initWithKey:@"text" ascending:NO] autorelease]];
[request setSortDescriptors:sortDescriptors];
Любой статический объект опасен для памяти, и вы используете их только в особых случаях. Зачем привязывать массив только с локальной областью к определенному адресу / блоку? Все это можно заменить одной строкой:
[request setSortDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortWithKey:@"text" ascending:NO]]];
… и это сделано.
Эта строка, вероятно, не нужна и, вероятно, вызовет проблемы позже:
self.articulationsArray = [NSMutableArray arrayWithArray:fetchResults];
Зачем вам нужен изменяемый массив извлеченных объектов? На самом деле вы не можете добавлять или удалять что-либо из массива напрямую, сохраняя целостность вашего графика без повторной выборки.
Просто:
self.articulationsArray = fetchResults;
в большинстве случаев будет работать нормально.
Чем больше объектов вы создаете, тем больше шансов на утечку вы создаете. Сделайте все как можно проще.
Комментарии:
1. Все хорошие моменты должным образом приняты к сведению. Это первый раз, когда я использую core data, и после этой утечки я начал копировать и вставлять материал отовсюду — я попробовал несколько разных методов, надеясь, что это исправит мою утечку.
Ответ №5:
Что ж… Я чувствую себя гусыней.
Когда я вернулся к своему первому TableViewController, я не выпускал articulationsArray.
Я использовал
- (void)viewDidUnload {
[self.articulationsArray release];
}
Когда я должен был использовать:
-(void)viewDidDisappear:(BOOL)animated {
[self.articulationsArray release];
}
viewDidUnload, никогда не вызывался.
Спасибо всем за вашу помощь.