У меня есть контроллер окон и контроллер просмотра, которые используют привязки основных данных, но я хочу иметь возможность иметь эти представления на самом деле, действительно получить освобождение. Затем я хочу, чтобы reset
управляемый объектObjectContext и в этот момент отказал как можно больше памяти.
Я обнаружил, что мне требуется unbind
вещи, которые я связал в Nib, или MOC сохраняет объекты Nib.
Проблема заключается в этой трассе EXEC_BAD_ACCESS:
Если я не отвязываю все привязки, даже те, которые созданы в Interface Builder, reset
в MOC, вызывает EXEC_BAD_ACCESS, потому что привязки пытаются отразить изменения в MOC в представлении, которое прошло через контроллер массива, который должно исчезнуть, но это не так.
Итак, я сделал это в оконном контроллере dealloc:
- (void) dealloc
{
NSLog(@"Wincon dealloc");
@autoreleasepool {
// Remove subview to ensure subview dealloc
[_viewController.view removeFromSuperviewWithoutNeedingDisplay];
// Tear down bindings to ensure MOC can reset
for (NSObject<NSKeyValueBindingCreation>* object in
@[_watcherAC, _watchersTimesTreeController, _watcherTableView, _itemsOutlineView])
{
for (NSString* binding in [object exposedBindings])
[object unbind:binding];
}
}
}
который запускается следующим образом:
- (void) switchToBackgroundMode
{
NSLog(@"SwitchToBackgroundMode");
// Hide the menu and dock icon
[NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory];
// Force every view to deallocate before reset
@autoreleasepool {
// Need to check loaded to prevent closing a closed window and
// triggering a second call to applicationShouldTerminateAfterLastWindowClosed
if ([self.wincon isWindowLoaded]) [self.wincon close];
self.wincon = nil;
}
NSLog(@"About to resetCoreDataStack");
[self resetCoreDataStack];
}
... и теперь я не получаю никаких ошибок с этим resetCoreDataStack
След стека содержит файл журнала, подобный этому:
2014-05-29 15:54:35.794 MyApp[10230:303] Switch to BG in appShouldTerminate
2014-05-29 15:54:35.794 MyApp[10230:303] SwitchToBackgroundMode
2014-05-29 15:54:35.808 MyApp[10230:303] Wincon dealloc
2014-05-29 15:54:35.830 MyApp[10230:303] About to resetCoreDataStack
2014-05-29 15:54:35.830 MyApp[10230:303] Reset Core Data
{Exception thrown iff wincon dealloc doesn't unbind everything}
И поэтому оконный контроллер dealloc определенно вызывается, когда он заполняется в autoreleasepool, но MOC reset вызывает EXEC_BAD_ACCESS, если этот wincon dealloc не делает unbind
на связке дерьма в Nib.
Итак, вопрос:
Учитывая, что Nib принадлежит пользовательскому оконному контроллеру (self.wincon
) с объектами arrayController, привязанными к внешнему управляемому объектуObjectContext, что нужно сделать, чтобы заставить все в Nib быть выпущенным и несвязанным? Есть ли какой-то шаг, который мне не хватает, что заставляет меня делать это развязывание вручную?
[EDIT] Новый код отладки:
NSLog(@"Wincon dealloc");
@autoreleasepool {
// Remove subview to ensure subview dealloc
[_viewController.view removeFromSuperviewWithoutNeedingDisplay];
_viewController = nil;
self.window = nil;
}
@autoreleasepool {
// Tear down bindings to ensure MOC can reset
for (NSObject<NSKeyValueBindingCreation>* object in
@[_watcherAC, _watchersTimesTreeController, _watcherTableView, /*_itemsOutlineView*/])
{
NSLog(@"Bindings for %@", [object className]);
for (NSString* binding in [object exposedBindings]) {
NSLog(@"BI for %@: %@", binding, [object infoForBinding:binding]);
[object unbind:binding];
}
}
приведенный ниже журнал - это bindingInfo для привязок, которые все еще живы, когда dealloc вызывается для windowController
2014-05-29 21:00:39.967 SaleWatch[11249:303] Wincon dealloc 2014-05-29 21:00:39.975 SaleWatch[11249:303] Bindings for NSArrayController 2014-05-29 21:00:39.978 SaleWatch[11249:303] Bindings for NSTreeController 2014-05-29 21:00:39.989 SaleWatch[11249:303] BI for contentSet: { NSObservedKeyPath = "selection.fetchTimesForOutlineView"; NSObservedObject = "[entity: SWWebStoreWatcher, number of selected objects: 1]"; } 2014-05-29 21:00:39.991 SaleWatch[11249:303] Bindings for NSTableView 2014-05-29 21:00:39.991 SaleWatch[11249:303] BI for selectionIndexes: { NSObservedKeyPath = selectionIndexes; NSObservedObject = "[entity: SWWebStoreWatcher, number of selected objects: 1]"; } 2014-05-29 21:00:40.001 SaleWatch[11249:303] BI for content: { NSObservedKeyPath = arrangedObjects; NSObservedObject = "[entity: SWWebStoreWatcher, number of selected objects: 1]"; } 2014-05-29 21:00:40.020 SaleWatch[11249:303] About to resetCoreDataStack
Я заставил wincon.window = nil в новом коде, и эти три объекта все еще не ноль, хотя outlineView treeController для этого стал нулевым. Здесь может быть цикл удержания, но я не вижу, как это будет моя ошибка... пока.