2014-12-06 9 views
6

Я запускаю свою программу, которая создает содержимое основных данных, которое отображается в NSOutlineView с использованием NSTreeController. Во второй раз, когда я запускаю свою программу, я хочу очистить содержимое своего NSTreeController, и я запускаю метод, вставленный ниже. Метод либо зависает в течение длительного времени (600 секунд), прежде чем он закончится, либо он сработает. Если у меня мало объектов (500-1000) в моем NStreeController, это занимает гораздо меньше времени по сравнению с тем, если у меня есть много (200 000) объектов, чтобы передать этот метод, если он вообще пройдет. Мне нужно знать, есть ли лучший способ очистить/обновить/сбросить содержимое моего NStreeController, чтобы очистить мой NSoutlineView, прежде чем снова заново запустите программу и снова заполните NStreeController. В частности, я хотел бы, чтобы мой NSOutlineView быстро ответил на изменения в содержании моего NSTreeController, и мне нужно, чтобы содержимое моих основных данных приводилось в действие NSTreeController, чтобы иметь возможность сброса.Сброс данных с данными, управляемых данными с данными ядра

-(void) cleanSDRDFileObjects 
{ 
    __weak __typeof__(self) weakSelf = self; 
    dispatch_async(dispatch_get_main_queue(), ^{  
     [weakSelf.outlineView collapseItem:nil collapseChildren:YES]; 
     [weakSelf.coreDataController._coreDataHelper.context performBlockAndWait:^{ 

      NSEntityDescription *entityDescription = [NSEntityDescription 
                entityForName:@"SDRDFileObject"          inManagedObjectContext:weakSelf.coreDataController._coreDataHelper.context]; 

      NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
      [request setEntity:entityDescription]; 

      NSArray * result = [weakSelf.coreDataController._coreDataHelper.context executeFetchRequest:request error:nil]; 
      for (id fileobject in result){ 
       [weakSelf.coreDataController._coreDataHelper.context deleteObject:fileobject]; 
      } 
      [weakSelf.coreDataController._coreDataHelper.context processPendingChanges]; 

      NSLog(@"Finished deleting all objects"); 
     }]; 
    }); 
} 

managedobjectcontext (context) выполняется как тип NSMainQueueConcurrencyType и метод выполняется в главном потоке. Приветствуются предложения по улучшению или полезные примеры для комбинации сброса/обновления NSOutlineView + Core Data. Благодарю. Cheers, Trond

В ответ на вопрос @TomHarringtons я сделал снимок моего Time Profiler. Я действительно надену t understand why it hangs on this method, however, after commenting this methods out (```processPendingChanges```), it still hangs and takes forever to finish (6 minutes). It seems the process gets stuck on the main thread and can t.

enter image description here

Когда я повторно запустить приложение, с processPendingChanges закомментирована его до сих пор висит.

enter image description here

Update

Я полагаю, что я решил эту проблему, но я немного неопределенными, почему это работает. Кажется, что мой первый метод перешел в неопределенный цикл, который не выпускал его объекты. Следующее простое решение сработало:

 __weak __typeof__(self) weakSelf = self; 
    dispatch_sync(dispatch_get_main_queue(), ^{ 
     [weakSelf.coreDataController._coreDataHelper.context reset]; 
     }); 

Я был уверен, что правильно опустошить контекст управляемого объекта, я бы удалить каждый объект в отдельности. Функция сброса кажется довольно грубой силой и действительно ли она очищает память и гарантирует, что все в порядке? Если кто-то хочет пролить свет на это, это будет оценено.

+0

will/didChangeValueForKey обычно вызывается из аксессуаров экземпляра 'self'. Почему бы вам назвать их этим методом? И NSTreeController даже не имеет keyPath «дети». У этого есть keyPath "childrenKeyPath". Независимо от всего этого ... вы ищете «remrangeObjects» ?? – stevesliva

+0

['rearrangeObjects'] (http://stackoverflow.com/questions/23773827/how-can-i-determine-if-apple-methods-are-asynchronous/) иногда планируют обновление GUI в очереди основного потока, поэтому он может иметь какое-то отношение к вашей проблеме. Тем не менее, ваше использование методов KVC пугающе, и вы должны изучить это до того, как когда-либо будете использовать will/didChangeValueForKey. Я также задаюсь вопросом, когда вы нажимаете изменения из фонового контекста в контекст mainThread/GUI. – stevesliva

+0

@stevesliva Спасибо за ваши комментарии. Я понимаю, что я скопировал и вставил свой код, когда я случайно тестировал KVO (Ill study). Я использовал KVO на организованных объектах (без успеха). Теперь я вижу, что мой делегат outlineView сбой, поскольку я удаляю объекты, особенно когда я удаляю объект перед удалением его дочерних элементов, а outlineview пытается обновить освобожденный элемент. Если у вас есть предложения по наилучшей практике в сбросе табличного представления или outlineview, основанного на Core Data, это было бы здорово. Я столкнулся с этой проблемой, но не могу найти хороших примеров того, как сбросить представление, основанное на Core Data. –

ответ

1

Если вы посмотрите на это снова, вы выбрали все объекты типа в performBlockAndWait - это блокирует основной поток, потому что у вас есть mainQueueConcurrency, и вы использовали версию andWait для выполненияBlock.

Затем вы удаляете каждый объект по одному. Эти объекты находятся в структуре данных дерева с включенным контурным просмотром (см. Сообщения KVO в трассировке стека). Эти объекты имеют множество отношений, которые должны поддерживаться основными данными, черт, вы даже можете иметь каскадное правило удаления. (см. propagateDelete и maintainInverseRelationship в трассировке стека). В любом случае вы начинаете запрашивать, чтобы и источник данных, и представление начали выполнять большую работу в основном потоке. Вы можете попробовать использовать дочерний MOC с privateQueueConcurrency, если хотите повторить все объекты в фоновом режиме.

Но, как и замечания, указанные:

NSManagedObjectContext-х reset определенно освобождает память, и это хорошо, что вы хотите сделать здесь: взорвать все прочь.

Это вызывает вопрос, почему вы загружаете модель из магазина на диске, в первую очередь.

Если вам нужны основные данные, но не постоянство между моментами запуска программы, вы можете инициализировать persistentStoreCoordinator хранилищем NSInMemoryStoreType, а не указывать его на URL-адрес файла.

+0

Я не знал о NSInMemoryStoreType, и я использую только Core Data как «In Memory» (не постоянство), так что это отличный совет! Спасибо! –

+0

Недавно я слышал, что это было предложено для тестирования ... вы можете написать модульные тесты, которые создают хранилища в памяти и отбрасывают их, не придумывая место на диске для вашей тестовой площадки. Но в этом случае он также подходит к законопроекту. – stevesliva

Смежные вопросы