Instance Method


Waits for any work scheduled by previous invocations of this method to complete, then invokes the passed-in block.


- (void)performActivityWithSynchronousWaiting:(BOOL)waitSynchronously usingBlock:(void (^)(void (^activityCompletionHandler)(void)))block;



If YES, the method does not return until previous activities are complete and the passed-in block has been invoked. If NO, the method might return before passed-in block is invoked. It might instead be invoked later, on the main thread, after previous activities are complete.


A block that performs work that might result in the presentation of a modal dialog.


The block is passed another block, the activity completion handler, which must be invoked when the activity is complete.

This method’s primary use is to wait for asynchronous saving. With asynchronous saving it is possible for the user to instigate a user interface action that might present modal dialog, a sheet for example, when asynchronous saving is about to fail and present an error alert sheet of its own, which would not work. This method solves that problem. If your NSDocument subclass supports asynchronous saving you should invoke this method around the performance of any work that might cause the presentation of a modal dialog, regardless of whether that work is performed synchronously or asynchronously. Here is a list of NSDocument methods whose default implementations invoke this method because they might present sheets, either to ask the user what to do as they begin their work or because they may fail and present errors to user:

More uses of this method may be added to NSDocument in the future.

This method must be invoked on the main thread. If YES is passed for the waitSynchronously parameter, the method waits on the main thread, blocking further user interaction with the document. The purpose of blocking the main thread is so that the user cannot continue to change the document while an activity is pending. This prevents, for example, the situation in which the user chooses to revert the document, but reverting does not happen immediately because asynchronous saving is still in progress, yet the user is able to continue changing the document, and then those changes are immediately discarded when the asynchronous saving is complete and the document is reverted. All of the NSDocument methods listed above pass YES for waitSynchronously.

You pass NO for waitSynchronously when the work to be done is instigated by the user so indirectly that the work might begin when a modal dialog is already being presented. For example, another method whose default implementation invokes this method, this time passing NO for waitSynchronously, is:


This method might present an error alert, but it is typically invoked by a timer. If it passed YES for waitSynchronously, and the timer fired while the user was looking at a sheet presented by a previous activity, blocking of the main thread would prevent the handling of the user interface events necessary to dismiss that sheet and complete that previous activity. Deadlock would result.

Whether you make this method wait synchronously or asynchronously to do your work is separate from whether your work is done synchronously or asynchronously. For example, as mentioned above, saveToURL:ofType:forSaveOperation:delegate:didSaveSelector:contextInfo: passes YES for waitSynchronously when it uses this method, even though the majority of the work it does may be done asynchronously.

You should not invoke this method during the invocation of the block passed to performSynchronousFileAccessUsingBlock: or in between the time performAsynchronousFileAccessUsingBlock: invokes the block passed to it and the time at which the corresponding file access completion handler is invoked. If you do, deadlock can result. In other words, you cannot begin a new activity as part of file access. You can, on the other hand, invoke performSynchronousFileAccessUsingBlock: or performAsynchronousFileAccessUsingBlock: as part of an activity.

Some asynchronous activities, such as saving, need to do work on the main thread as they are completing. A deadlock would be inevitable if there were no way to interrupt this method’s blocking of the main thread. See continueAsynchronousWorkOnMainThreadUsingBlock: to find out how to interrupt this method’s blocking of the main thread.

See Also



Invokes the passed-in block to avoid a deadlock if performActivityWithSynchronousWaiting:usingBlock: is being invoked recursively.


Invokes the passed-in block on the main thread.


Waits for any scheduled file access to complete but without blocking the main thread, then invokes the passed-in block.


Waits for any scheduled file access to complete, then invokes the passed-in block.