Macos 10.15 beta Cocoa Apps crash with mainWindow.representedURL KVO error message
Original Reporter info from Mantis: djenkins @dfjenkins
-
Reporter name: David Jenkins
Original Reporter info from Mantis: djenkins @dfjenkins
- Reporter name: David Jenkins
Description:
On Macos 10.15 beta Cocoa apps crash with following message:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Cannot update for observer &LtPos;NSFrontmostDocumentWindowObserver 0x7fff8ec52208> for the key path "mainWindow.representedURL" from &LtPos;TCocoaApplication 0x100d089a0>, most likely because the value for the key "mainWindow" has changed without an appropriate KVO notification being sent. Check the KVO-compliance of the TCocoaApplication class.'
Crash can occur on on startup (for our app) or also reported to happen when a two form app when opening second form as modal dialog.
Steps to reproduce:
Build app for cocoa 64 with multiple forms
Additional information:
Error is caused because Cocoa currently doesn't run through base level NSApplication.run and thus appropriate ._isrunning flag is not set (notice that this also required the override of NSApplication.isRunning done for Mantis 32177)
NSFrontmostDocumentWindowObserver registers for all changes to mainWindow.representedURL. During initialization of NSApplication (down inside Cocoa code) calls to willChangeValueForKey() and didChangevalueForKey() are made to '_mainWindow' or 'mainWindow' depending on state of _isRunning flag (not from calls to .isRunning but from the memory locaiton where it is stored) and NSapplication.isActive. Because we don't go through NSApplication.run the bit for .isRunning is never set and calls to willChangevalueForKey(), didChangevalueForKey() do not happen appropriately for 'mainWindow'.
The crash occurs when _handleApplicationActivated calls removeObserverForKeyPath() on an observer object that is supposed to be set up for 'mainWindow' but it was never actually set up i.e. addObserverForKeyPath() was never called. Documentation for removeObserverForKeyPath() indicates that removing an object that hasn't been set up with addObserverForKeyPath() is an error condition. That is the condition we are hitting.
Suggested fix (patch attached) is to run through NSApplication.run first and then jump into our aloop().
Accomplished by removing TCocoaApplication.isRunning and TCocoaApplication.run methods thus allowing NSApplication.run to be called and set up NSRunloop and make first call to nextEventMatching:unitDate, etc. On first pass through nextEventMatching. (as caught by isRun = false) we grab control and call aloop.
Mantis conversion info:
- Mantis ID: 35702
- Version: 2.0.3 (SVN)
- Fixed in revision: 61355 (#a4da0d9e)