我应该在windowController的dealloc中取消绑定cocoa绑定吗?

时间:2014-05-29 23:04:27

标签: objective-c macos core-data automatic-ref-counting cocoa-bindings

我有使用核心数据绑定的窗口控制器和视图控制器,但我希望能够真正获得这些视图,真正获得解除分配。然后,我想reset managedObjectContext,并且在那时放弃了尽可能多的内存。

我发现我需要unbind我在Nib中绑定的内容,或者MOC会保留Nib对象。

问题是这个EXEC_BAD_ACCESS跟踪:

enter image description here

如果我没有取消绑定所有绑定,即使是在Interface Builder中创建的绑定,MOC上的reset也会导致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重置会导致EXEC_BAD_ACCESS,除非wincon dealloc对Nib中的一堆垃圾进行unbind

所以问题是:

如果一个自定义窗口控制器(self.wincon)拥有一个绑定到外部managedObjectContext的arrayController对象的Nib,那么需要做什么来强制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];
        }
    }

下面的日志是为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,这三个对象仍然没有,尽管treeController用于的outlineView确实变为零。这里可能有一个保留周期,但我不知道它是如何成为我的错......但是。

0 个答案:

没有答案