1
votes

Problem: closing the document window produces the following exception:

An instance 0x600000140630 of class SimpleApp.Document was deallocated while key value 
observers were still registered with it. Current observation info:  <NSKeyValueObservationInfo 0x6100000424f0> …

<NSKeyValueObservance 0x6100000c2f40: Observer: 0x6280000c7a10, Key path: managedObjectContext, Options: <New: NO, Old: NO, Prior: NO> Context: 0x0, Property: 0x6100000429a0>

and

-[NSAutoreleasePool drain]: This pool has already been drained, do not release it (double release).

Here’ what I’ve done:

Created a new Xcode Project using:

  • Use Storyboards
  • Create Document-Based Application
  • Use Core Data

In Document.xcdatamodeld

  • created an Entity (Part) with 2 attributes, width and length

In Main.storyboard,

  • dragged a table view (view based), 2 buttons (“Add” and “Remove”) and an ArrayController to the view controller

  • ArrayController mode set to Entity

Bindings:

  • tableView content: ArrayController arrangedObjects, Selection Indexes: ArrayController selectionIndexes
  • the 2 table view cells were bound to Table Cell View, keyPath: objectValue.width and objectValue.length

Now the first problem was to bind the ArrayController managedObjectContext. I needed a reference to the Document subclass. So I added

weak var document: Document? {
    didSet {
        print("ViewController, document didSet")
    }
}

in ViewController and bound the ArrayController managed object context to it (document.managedObjectContext).

After trying, without success, to set this var in various places (ViewController.viewDidLoad() , in a NSWindowController subclass's windowDidLoad(), NSDocumentController.sharedDocumentController().documentForWindow(self.window!) was always nil.

I made it work using the following in Document.makeWindowControllers()

if let viewController = windowController.contentViewController {
     viewController.setValue(self, forKey: "document")
}

So, now I can create a new document, and save it, open a saved document but as soon as I close the window I get the previous exception. I added deinit methods to the view controller and the document and the exception occurs after Document.deinit is called but before ViewController.deinit. So it looks like the array controller is still observing the Document managedObjectContext which no longer exists.

Maybe I’m missing something obvious here, but I can’t find a simple example on how to use storyboards, array controller and document together. BTW, I also tried without Core Data and got the same exception.

UPDATED

I've made a github project https://github.com/Miyan0/SimpleApp.git

The steps to reproduce the crash:

  • create a new document
  • save it
  • reopen the document
  • make any modifications
  • click the closebox (without saving)
  • crash
1
Please provide sample code so it is easier to help you. - Marek H
Thanks Marek, I've updated the post. I thought the problem was with document's autosavesInPlace but even if set to false, I can crash the app if I close a modified document and choose "don't save" in the save dialog. - amasse
It gives me this warning imgur.com/MgBtblX, after it crashes - Marek H
One note: setNil while binding is still being connected can be the source of crash - Marek H
Well, that's strange. I never get this warning... About setting nil for the array controller managedObjectContext, I get the same exception with or without it. This was a try to crush this bug. I'm on El Capitan 10.11.1 btw. - amasse

1 Answers

0
votes

Looks like the only way to solve this is by changing the document's reference in ViewController from weak to strong.

I was afraid it may cause a retain cycle but it doesn't (according to the print statements and deinit methods for ViewController and Document). I tried to cover all possibles cases and even if sometimes the document isn't deallocated after closing it's window, it will eventually be deallocated when a new document is created or another one is modified.