0

I am writing an app that needs to have multiple documents in one window (as was asked about here. So I can't just make it a "document-based application", but I am still trying to use the document architecture to save the individual files.

What I'm specifically trying to do is close all open documents, and preferably save them if they have been modified. It seems like the best way to do this is to call the closeAllDocumentsWithDelegate method of the shared document controller. But I don't know what parameters to pass it. The docs say it is:

func closeAllDocumentsWithDelegate(_ delegate: AnyObject?, didCloseAllSelector didCloseAllSelector: Selector, contextInfo contextInfo: UnsafeMutablePointer)

They don't say what these mean, though. What delegate, selector and contextInfo should I be calling? I can't find examples of this method being used successfully. I tried seeing if I could get away with self and nil just to get it to compile:

SharedDocumentController.sharedDocumentController().closeAllDocumentsWithDelegate(self, didCloseAllSelector: nil, contextInfo: nil)

But then I get the error "Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)", which I'm told is a null pointer exception. So at least one of those nils is a no-go, probably because of a forced unwrap somewhere. Fine, but what would I put there instead?

EDIT: as requested below, I am attaching a pic of the stacktrace: stacktrace

And of the console:

2016-06-29 12:00:46.397 FourthDraftBrouillon[54275:6093667] An uncaught exception was raised
2016-06-29 12:00:46.397 FourthDraftBrouillon[54275:6093667] *** -[__NSArray0 objectAtIndex:]: index 2 beyond bounds for empty NSArray
2016-06-29 12:00:46.398 FourthDraftBrouillon[54275:6093667] (
    0   CoreFoundation                      0x00007fff981034f2 __exceptionPreprocess + 178
    1   libobjc.A.dylib                     0x00007fff888b8f7e objc_exception_throw + 48
    2   CoreFoundation                      0x00007fff98123205 -[__NSArray0 objectAtIndex:] + 101
    3   libswiftCore.dylib                  0x0000000100075f4d _TFVs12_ArrayBuffer19_getElementSlowPathfSiPs9AnyObject_ + 125
    4   libswiftCore.dylib                  0x0000000100075370 _TFVs12_ArrayBuffer10getElementfTSi20wasNativeTypeCheckedSb_x + 144
    5   libswiftCore.dylib                  0x000000010008e60a _TFSag9subscriptFSix + 138
    6   FourthDraftBrouillon                0x0000000100007c6f _TFC20FourthDraftBrouillon14ViewController14collectionViewfTCSo16NSCollectionView35itemForRepresentedObjectAtIndexPathCSo11NSIndexPath_CSo20NSCollectionViewItem + 799
    7   FourthDraftBrouillon                0x0000000100007e2f _TToFC20FourthDraftBrouillon14ViewController14collectionViewfTCSo16NSCollectionView35itemForRepresentedObjectAtIndexPathCSo11NSIndexPath_CSo20NSCollectionViewItem + 79
    8   AppKit                              0x00007fff92bc40f6 -[_NSCollectionViewDataSourceAdapter collectionView:itemForRepresentedObjectAtIndexPath:] + 487
    9   UIFoundation                        0x00007fff95acd3ff -[_NSCollectionViewCore _createPreparedCellForItemAtIndexPath:withLayoutAttributes:applyAttributes:] + 81
    10  UIFoundation                        0x00007fff95ace6f6 -[_NSCollectionViewCore _updateVisibleCellsNow:] + 2167
    11  UIFoundation                        0x00007fff95ad0b24 -[_NSCollectionViewCore _layoutItems] + 208
    12  AppKit                              0x00007fff92bb76aa -[NSCollectionView layout] + 80
    13  AppKit                              0x00007fff923f14eb -[NSView _doLayout] + 53
    14  AppKit                              0x00007fff923f11a3 -[NSView _layoutSubtreeWithOldSize:] + 324
    15  AppKit                              0x00007fff923f13ff -[NSView _layoutSubtreeWithOldSize:] + 928
    16  AppKit                              0x00007fff923f13ff -[NSView _layoutSubtreeWithOldSize:] + 928
    17  AppKit                              0x00007fff923f13ff -[NSView _layoutSubtreeWithOldSize:] + 928
    18  AppKit                              0x00007fff923f13ff -[NSView _layoutSubtreeWithOldSize:] + 928
    19  AppKit                              0x00007fff923f06dc -[NSView layoutSubtreeIfNeeded] + 950
    20  AppKit                              0x00007fff92410025 -[NSWindow(NSConstraintBasedLayout) _layoutViewTree] + 82
    21  AppKit                              0x00007fff92482603 -[NSWindow(NSConstraintBasedLayout) layoutIfNeeded] + 244
    22  AppKit                              0x00007fff92b191f5 ___NSWindowGetDisplayCycleObserver_block_invoke6358 + 218
    23  AppKit                              0x00007fff924945fc __37+[NSDisplayCycle currentDisplayCycle]_block_invoke + 719
    24  QuartzCore                          0x00007fff91702f71 _ZN2CA11Transaction19run_commit_handlersE18CATransactionPhase + 85
    25  QuartzCore                          0x00007fff9170242c _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 160
    26  QuartzCore                          0x00007fff917020ec _ZN2CA11Transaction6commitEv + 508
    27  AppKit                              0x00007fff925d9650 -[_NSScrollingConcurrentMainThreadSynchronizer _synchronize:completionHandler:] + 391
    28  AppKit                              0x00007fff925d9496 __80-[_NSScrollingConcurrentMainThreadSynchronizer initWithSharedData:constantData:]_block_invoke + 144
    29  libdispatch.dylib                   0x00000001005cbcc5 _dispatch_client_callout + 8
    30  libdispatch.dylib                   0x00000001005deba6 _dispatch_source_latch_and_call + 3387
    31  libdispatch.dylib                   0x00000001005d0cd8 _dispatch_source_invoke + 978
    32  libdispatch.dylib                   0x00000001005e3012 _dispatch_main_queue_callback_4CF + 1153
    33  CoreFoundation                      0x00007fff980b89e9 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
    34  CoreFoundation                      0x00007fff980778dd __CFRunLoopRun + 1949
    35  CoreFoundation                      0x00007fff98076ed8 CFRunLoopRunSpecific + 296
    36  HIToolbox                           0x00007fff89e0b935 RunCurrentEventLoopInMode + 235
    37  HIToolbox                           0x00007fff89e0b76f ReceiveNextEventCommon + 432
    38  HIToolbox                           0x00007fff89e0b5af _BlockUntilNextEventMatchingListInModeWithFilter + 71
    39  AppKit                              0x00007fff9233cefa _DPSNextEvent + 1067
    40  AppKit                              0x00007fff9233c32a -[NSApplication _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 454
    41  AppKit                              0x00007fff92330e84 -[NSApplication run] + 682
    42  AppKit                              0x00007fff922fa46c NSApplicationMain + 1176
    43  FourthDraftBrouillon                0x0000000100008d04 main + 84
    44  libdyld.dylib                       0x00007fff930135ad start + 1
    45  ???                                 0x0000000000000003 0x0 + 3
)
2016-06-29 12:00:46.399 FourthDraftBrouillon[54275:6093667] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArray0 objectAtIndex:]: index 2 beyond bounds for empty NSArray'
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff981034f2 __exceptionPreprocess + 178
    1   libobjc.A.dylib                     0x00007fff888b8f7e objc_exception_throw + 48
    2   CoreFoundation                      0x00007fff98123205 -[__NSArray0 objectAtIndex:] + 101
    3   libswiftCore.dylib                  0x0000000100075f4d _TFVs12_ArrayBuffer19_getElementSlowPathfSiPs9AnyObject_ + 125
    4   libswiftCore.dylib                  0x0000000100075370 _TFVs12_ArrayBuffer10getElementfTSi20wasNativeTypeCheckedSb_x + 144
    5   libswiftCore.dylib                  0x000000010008e60a _TFSag9subscriptFSix + 138
    6   FourthDraftBrouillon                0x0000000100007c6f _TFC20FourthDraftBrouillon14ViewController14collectionViewfTCSo16NSCollectionView35itemForRepresentedObjectAtIndexPathCSo11NSIndexPath_CSo20NSCollectionViewItem + 799
    7   FourthDraftBrouillon                0x0000000100007e2f _TToFC20FourthDraftBrouillon14ViewController14collectionViewfTCSo16NSCollectionView35itemForRepresentedObjectAtIndexPathCSo11NSIndexPath_CSo20NSCollectionViewItem + 79
    8   AppKit                              0x00007fff92bc40f6 -[_NSCollectionViewDataSourceAdapter collectionView:itemForRepresentedObjectAtIndexPath:] + 487
    9   UIFoundation                        0x00007fff95acd3ff -[_NSCollectionViewCore _createPreparedCellForItemAtIndexPath:withLayoutAttributes:applyAttributes:] + 81
    10  UIFoundation                        0x00007fff95ace6f6 -[_NSCollectionViewCore _updateVisibleCellsNow:] + 2167
    11  UIFoundation                        0x00007fff95ad0b24 -[_NSCollectionViewCore _layoutItems] + 208
    12  AppKit                              0x00007fff92bb76aa -[NSCollectionView layout] + 80
    13  AppKit                              0x00007fff923f14eb -[NSView _doLayout] + 53
    14  AppKit                              0x00007fff923f11a3 -[NSView _layoutSubtreeWithOldSize:] + 324
    15  AppKit                              0x00007fff923f13ff -[NSView _layoutSubtreeWithOldSize:] + 928
    16  AppKit                              0x00007fff923f13ff -[NSView _layoutSubtreeWithOldSize:] + 928
    17  AppKit                              0x00007fff923f13ff -[NSView _layoutSubtreeWithOldSize:] + 928
    18  AppKit                              0x00007fff923f13ff -[NSView _layoutSubtreeWithOldSize:] + 928
    19  AppKit                              0x00007fff923f06dc -[NSView layoutSubtreeIfNeeded] + 950
    20  AppKit                              0x00007fff92410025 -[NSWindow(NSConstraintBasedLayout) _layoutViewTree] + 82
    21  AppKit                              0x00007fff92482603 -[NSWindow(NSConstraintBasedLayout) layoutIfNeeded] + 244
    22  AppKit                              0x00007fff92b191f5 ___NSWindowGetDisplayCycleObserver_block_invoke6358 + 218
    23  AppKit                              0x00007fff924945fc __37+[NSDisplayCycle currentDisplayCycle]_block_invoke + 719
    24  QuartzCore                          0x00007fff91702f71 _ZN2CA11Transaction19run_commit_handlersE18CATransactionPhase + 85
    25  QuartzCore                          0x00007fff9170242c _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 160
    26  QuartzCore                          0x00007fff917020ec _ZN2CA11Transaction6commitEv + 508
    27  AppKit                              0x00007fff925d9650 -[_NSScrollingConcurrentMainThreadSynchronizer _synchronize:completionHandler:] + 391
    28  AppKit                              0x00007fff925d9496 __80-[_NSScrollingConcurrentMainThreadSynchronizer initWithSharedData:constantData:]_block_invoke + 144
    29  libdispatch.dylib                   0x00000001005cbcc5 _dispatch_client_callout + 8
    30  libdispatch.dylib                   0x00000001005deba6 _dispatch_source_latch_and_call + 3387
    31  libdispatch.dylib                   0x00000001005d0cd8 _dispatch_source_invoke + 978
    32  libdispatch.dylib                   0x00000001005e3012 _dispatch_main_queue_callback_4CF + 1153
    33  CoreFoundation                      0x00007fff980b89e9 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
    34  CoreFoundation                      0x00007fff980778dd __CFRunLoopRun + 1949
    35  CoreFoundation                      0x00007fff98076ed8 CFRunLoopRunSpecific + 296
    36  HIToolbox                           0x00007fff89e0b935 RunCurrentEventLoopInMode + 235
    37  HIToolbox                           0x00007fff89e0b76f ReceiveNextEventCommon + 432
    38  HIToolbox                           0x00007fff89e0b5af _BlockUntilNextEventMatchingListInModeWithFilter + 71
    39  AppKit                              0x00007fff9233cefa _DPSNextEvent + 1067
    40  AppKit                              0x00007fff9233c32a -[NSApplication _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 454
    41  AppKit                              0x00007fff92330e84 -[NSApplication run] + 682
    42  AppKit                              0x00007fff922fa46c NSApplicationMain + 1176
    43  FourthDraftBrouillon                0x0000000100008d04 main + 84
    44  libdyld.dylib                       0x00007fff930135ad start + 1
    45  ???                                 0x0000000000000003 0x0 + 3
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Community
  • 1
  • 1
Displaced Hoser
  • 871
  • 3
  • 13
  • 35

1 Answers1

0

This method simply executes -canCloseDocumentWithDelegate:shouldCloseSelector:contextInfo: for all open windows. So look at its documentation. (Linked above.)

The short form: You can pass a delegate object, which will be informed about the close request via the method that responds to the selector, you passed.

So let's say, the object that should be informed is the app delegate, then you pass this as delegate parameter and write a method in the app delegate, whose selector you pass as selector parameter. In Swift you must decorate that method (Swift: function) with @objc.

The contextInfo is any user-definable data to pass or not. It is simply passed through. It is a "communication channel" from caller in your code to the delegate method, i. e. signaling the reason for the close. You can pass nil for it.

Even I did not test it, but typically you can pass nil for delegate, too. In such a case you should be able to pass NULL (it is no type) for the selector. Just try it. Then you do not need an empty method.

Amin Negm-Awad
  • 16,582
  • 3
  • 35
  • 50
  • Is the selector passed to `canCloseDocument` or is it called once after all documents are closed? – Willeke Jun 28 '16 at 21:43
  • *The didCloseAllSelector callback method is called with YES if all documents are closed, and NO otherwise. Pass the contextInfo object with the callback. The didCloseAllSelector callback method should have the following signature:* – Amin Negm-Awad Jun 28 '16 at 22:02
  • Ah, I see. Edit that. – Amin Negm-Awad Jun 28 '16 at 22:25
  • Thanks... so, I did look at the document for -canCloseDocumentWithDelegate before asking this question, but it wasn't any clearer to me than closeAllDocumentsWithDelegate. I don't know what a contextInfo object is or which one I would pass, and have only a vague and theoretical idea of what a selector is. Suppose I just want the documents to close and nothing more to happen - can I just write a blank method in the app delegate for the selector to call, and call the app delegate as a delegate? And then what is my contextInfo - is it okay if *that* is nil as long as the selector is not? – Displaced Hoser Jun 29 '16 at 03:04
  • Tried the edited version of Amin's response above, nulling everything. NULL for the selector won't compile: Xcode said "Cannot convert value of type '()' to expected argument type 'Selector'". So I tried setting the selector to nil instead. Now when I run the relevant portion of code, the app crashes and spews a bunch of stuff onto the console, most notably: > Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArray0 objectAtIndex:]: index 3 beyond bounds for empty NSArray' > libc++abi.dylib: terminating with uncaught exception of type NSException – Displaced Hoser Jun 29 '16 at 11:47
  • The exceptions above appear to have to do with my CollectionView data source, which displays the open documents in CollectionViewItems. Should I be putting the relevant data source method in a do-try-catch block? – Displaced Hoser Jun 29 '16 at 11:57
  • Please add the complete stack trace to your Q. Obviously someone is accessing an empty array. – Amin Negm-Awad Jun 29 '16 at 12:04
  • @DisplacedHoser Yes, did not keep in mind that you are using Swift. Of course you have to use a nil selector. – Amin Negm-Awad Jun 29 '16 at 12:05
  • Stacktrace attached. My CollectionView data source gets its info from the array of documents in the shared document controller, and I would imagine that that's the empty array that's the problem; just not sure how to fix it. – Displaced Hoser Jun 29 '16 at 16:08
  • Well, really the stack trace of the crash. It should be in the console. And please add it as text, not as image. – Amin Negm-Awad Jun 29 '16 at 16:37
  • Console added as text above. – Displaced Hoser Jun 30 '16 at 21:34
  • Thank you. `_TFVs12_ArrayBuffer19_getElementSlowPathfSiPs9AnyObject_` is your code? – Amin Negm-Awad Jun 30 '16 at 22:20
  • No, it's not. It was in the console. I've no idea what it was doing there. (BTW, are we supposed to take this to chat?) – Displaced Hoser Jun 30 '16 at 23:38
  • Of course, this is in the console. But the stack trace contains identifiers of functions of the program. The function that contains the malicious code is the one mentioned above. Did you set a exception breakpoint? (We can continue in chat) – Amin Negm-Awad Jul 01 '16 at 04:42
  • Taken up in private chat room. – Displaced Hoser Jul 01 '16 at 15:46