ste*_*iva 5 macos core-data objective-c cocoa-bindings automatic-ref-counting
我有使用核心数据绑定的窗口控制器和视图控制器,但我希望能够真正获得这些视图,真正取消分配.然后我想要resetmanagedObjectContext,并且在那时放弃了尽可能多的内存.
我发现我需要unbind在Nib中绑定的东西,或者MOC保留Nib对象.
问题是这个EXEC_BAD_ACCESS跟踪:

如果我没有取消绑定所有绑定,即使是在Interface Builder reset上创建的那些绑定,也会导致EXEC_BAD_ACCESS,因为绑定试图通过应该消失的数组控制器反映视图中MOC的变化,但不是"T.
所以我在窗口控制器的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];
}
}
}
Run Code Online (Sandbox Code Playgroud)
以这种方式触发:
- (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];
}
Run Code Online (Sandbox Code Playgroud)
......现在我没有任何错误 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}
Run Code Online (Sandbox Code Playgroud)
因此窗口控制器dealloc在autoreleasepool中被填充时肯定会被调用,但是MOC重置会导致EXEC_BAD_ACCESS,除非wincon dealloc unbind在Nib中的一堆垃圾上执行.
所以问题是:
给定一个由自定义窗口controller(self.wincon)拥有的Nib ,并将arrayController对象绑定到外部managedObjectContext,需要做什么来强制Nib中的所有内容被释放和解除绑定?是否有一些我缺少的步骤导致我必须手动取消绑定?
[编辑]一些新的调试代码:
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];
}
}
Run Code Online (Sandbox Code Playgroud)
下面的日志是在为windowController调用dealloc时绑定仍然存活的bindingInfo
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,这三个对象仍然不是nil,尽管treeController的outlineView确实变为nil.这里可能有一个保留周期,但我不知道它是怎么回事.
| 归档时间: |
|
| 查看次数: |
975 次 |
| 最近记录: |