NSFilePresenter

The NSFilePresenter protocol should be implemented by objects that allow the user to view or edit the content of files or directories. You use file presenters in conjunction with an NSFileCoordinator object to coordinate access to a file or directory among the objects of your application and between your application and other processes. When changes to an item occur, the system notifies objects that adopt this protocol and gives them a chance to respond appropriately.
More...

You use the methods of this protocol to respond to actions about to be taken on the presented file or directory. When another object or process uses a file coordinator to begin reading or writing a file or directory, the file coordinator notifies all presented objects interested in the item first. It notifies the presenter objects by invoking one of the methods defined by this protocol on that object. The actual invocation of that method occurs on the operation queue in the presentedItemOperationQueue property. Your file presenter must provide this queue. If your queue supports the concurrent execution of operations, the methods of your presenter object must be thread-safe and able to run in multiple queues simultaneously.

You can use file presenters to coordinate access to a file or directory among your application’s objects. If another process uses a file coordinator for the same file or directory, your presenter objects are similarly notified whenever the other process makes its changes. Your presenter objects are not notified about changes made directly using low-level read and write calls to the file. Only changes that go through a file coordinator result in notifications.

File Presenters and iOS

If your app enters the background with an active file presenter, any other processes that perform a coordinated read or write on the presented file can deadlock. To prevent this situation, call removeFilePresenter: to remove the file presenter in the applicationDidEnterBackground: method or in response to a UIApplicationDidEnterBackgroundNotification notification. Call addFilePresenter: to add the file presenter again in the applicationWillEnterForeground: method or in response to a UIApplicationWillEnterForegroundNotification notification.

Note

The UIDocument class automatically removes itself when your app goes to the background. It automatically adds itself again when your app returns to the foreground.

Declaration

Discussion

File presenters must implement this property and use it to return the file or directory of interest. If this object presents a group of related files that all reside in the same directory, specify the URL of the directory instead of creating separate presenter objects for each file. For example, a single-window application that manages multiple files inside a project directory should monitor the project directory.

The URL associated with your item may be requested by objects not associated with your presenter. Therefore, your implementation of the accessor method for this property must be thread safe and capable of running in multiple dispatch or operation queues simultaneously.

Declaration

Discussion

As other objects and processes interact with the presented item, the system queues relevant messages for this presenter object on the operation queue in this property. For example, when another process attempts to read a file presented by this object, the system places an invocation of this object’s relinquishPresentedItemToReader: method on the queue for execution. The other process must wait to read the file until that method is dequeued and executed. Requests for an object’s presented URL are not processed on this queue.

Declaration

Discussion

This property supports App Sandbox in OS X.

Some apps require access to secondary files or directories with names that are related to the primary, user-selected file. For example, a subtitle file, by convention, has the same name as its corresponding movie file, but with a different filename extension. If a movie player is sandboxed, an NSOpenPanel object will grant access only to the user-selected movie file (the primary item) and not its associated subtitle file (the secondary item).

To gain access to a secondary item, first register an NSFilePresenter object for it. At any point in its existence, a secondary item must be able to return an NSURL object to its primary item. This is done by using this property. When done accessing the secondary item, unregister the file presenter object.

Declaration

Parameters

reader

A Block object that takes another block as a parameter and returns no value. The reacquirer block is one you pass to the reader block so that your object can be notified when the reader is done. If your object does not need to be notified, it can pass nil for the reacquirer block.

Discussion

You use this method to provide an appropriate response when another object wants to read from your presented URL. For example, when this method is called, you might temporarily stop making changes to the file or directory. After taking any appropriate steps, you must execute the block in the reader parameter to let the waiting object know that it may now proceed with its task. If you want to be notified when the reader has completed its task, pass your own block to the reader and use that block to reacquire the file or URL for your own uses.

Important

If you implement this method, you must execute the block in the reader parameter as part of your implementation. The system waits for you to execute that block before allowing the reader to operate on the file. Therefore, failure to execute the block could stall threads in your application or other processes until the user takes corrective actions.

The following listing shows a simple implementation of this method that sets a Boolean flag that the file being monitored is not writable at the moment. After setting the flag, it executes the reader block and passes in yet another block for the reader to execute when it is done.

Declaration

Parameters

writer

A Block object that takes another block as a parameter and returns no value. The reacquirer block is one you pass to the writer block so that your object can be notified when the writer is done. If your object does not need to be notified, it can pass nil for the reacquirer block.

Discussion

You use this method to provide an appropriate response when another object wants to write to your presented URL. For example, when this method is called, you would likely stop making changes to the file or directory. After taking any appropriate steps, you must execute the block in the writer parameter to let the waiting object know that it may now proceed with its task. If you want to be notified when the writer has completed its task, pass your own block to the writer and use that block to reacquire the file or URL for your own uses.

Important

If you implement this method, you must execute the block in the writer parameter at the end of your implementation. The system waits for you to execute that block before allowing the writer to operate on the file. Therefore, failure to execute the block could stall threads in your application or other processes.

If the writer changes the file or directory, you do not need to incorporate those changes in your reacquirer block. Instead, implement the presentedItemDidChange method and use it to detect when a writer actually wrote its changes to disk.

The following listing shows a simple implementation of this method that sets a Boolean flag that the file being monitored is not writable at the moment. After setting the flag, it executes the writer block and passes in yet another block for the writer to execute when it is done.

Parameters

completionHandler

The Block object to call after you save your changes. If you saved your changes successfully, pass nil for the block’s errorOrNil parameter; otherwise, pass an error object indicating why the changes could not be saved.

Discussion

The file coordinator calls this method to ensure that all objects trying to access the file or directory see the same contents. Implement this method if your object can change the presented item in a way that requires you to write those changes back to disk. If your presenter object does not make changes that need to be saved, you do not need to implement this method.

Important

If you implement this method, you must execute the block in the completionHandler parameter at the end of your implementation. The system waits for you to execute that block before allowing other objects to operate on the file. Therefore, failure to execute the block could stall threads in your application or other processes.

Parameters

completionHandler

The Block object to call after updating your data structures. Pass nil to the block’s errorOrNil parameter if you were able to successfully prepare for the deletion of the item. Pass an error object if your object could not prepare itself properly.

Discussion

A file coordinator calls this method when your object’s presented item is about to be deleted. You can use this method to perform any actions that are needed to prepare for the deletion. For example, document objects typically use this method to close the document.

Important

If you implement this method, you must execute the block in the completionHandler parameter at the end of your implementation. The system waits for you to execute that block before allowing the other object to delete the file or directory. Therefore, failure to execute the block could stall threads in your application or other processes.

Availability

See Also

Declaration

Swift

optionalfuncpresentedItemDidChange()

Objective-C

- (void)presentedItemDidChange

Discussion

You can use this method to update your internal data structures to reflect the changes to the presented item. This method reports both changes to the file’s contents, such as the data in a file or the files in a directory, or the attributes of the item, such as whether the Hide extension checkbox of a file was toggled.

Because this method notifies you of both attribute and content changes, you might want to check the modification date before needlessly rereading the contents of a file. To do that, you must store the date when your object last made changes to the file and compare that date with the item’s current modification date. Use the coordinateReadingItemAtURL:options:error:byAccessor: method of a file coordinator to ensure exclusive access to the file when reading the current modification date.

Declaration

Parameters

version

The file version object containing information about the new file version.

Discussion

Your delegate can use this method to determine how to incorporate data from the new version of the file or file package. If the file has not been modified by your code, you might simply update to the new version quietly. However, if your application has its own changes, you might need to ask the user how to proceed.

Declaration

Parameters

version

The file version object containing information about the version that was removed.

Discussion

Your delegate can use this method to determine how to handle the loss of the specified file version. You can try to revert the presented document to a previous version or you might want to prompt the user about how to proceed.

Declaration

Parameters

version

The version object containing the conflicting change.

Discussion

Your delegate can use this method to respond to the resolution of a version conflict by a different file presenter. This might occur if a version of your application running on another device resolves the conflict first. You might then use this method to update your user interface to indicate that there is no longer a conflict.

Declaration

Parameters

The URL of the item inside the presented directory that lost a version. The item need not be at the top level of the presented directory but may itself be inside a nested subdirectory.

version

The file version object containing information about the version that was removed.

Discussion

Your delegate can use this method to determine how to handle the loss of the specified file version. For an old version, you might not have to do anything. However, if your application is currently using the lost version, you would need to update your application’s user interface or prompt the user about how to proceed.

Parameters

The URL of the item inside the presented directory that was in conflict. The item need not be at the top level of the presented directory but may itself be inside a nested subdirectory.

version

The version object containing the conflicting change.

Discussion

Your delegate can use this method to respond to the resolution of a version conflict by a different file presenter. This might occur if a version of your application running on another device resolves the conflict first. You might then use this method to update your user interface to indicate that there is no longer a conflict.

Parameters

url

The URL of the item being deleted from the presented directory. The item need not be at the top level of the presented directory but may itself be inside a nested subdirectory.

completionHandler

The Block object to call after updating your data structures. Pass nil to the block’s errorOrNil parameter if you were able to successfully prepare for the deletion of the item. Pass an error object if your object could not prepare itself properly.

Discussion

This method is relevant for applications that present directories. This might occur if the delegate manages the contents of a directory or manages a file that is implemented as a file package. When called, your implementation of this method should take whatever actions needed to update your application to handle the deletion of the specified file.

Important

If you implement this method, you must execute the block in the completionHandler parameter at the end of your implementation. The system waits for you to execute that block before allowing the other object to delete the item at the specified URL. Therefore, failure to execute the block could stall threads in your application or in other processes.

Declaration

Parameters

url

The URL of the item being added to the presented directory. The item need not be at the top level of the presented directory but may itself be inside a nested subdirectory.

Discussion

This method is relevant for applications that present directories. This might occur if the delegate manages the contents of a directory or manages a file that is implemented as a file package. Your implementation of this method should take whatever actions necessary to incorporate the new file or directory into the presented content. For example, you might add the new item to your application’s data structures and refresh your user interface.

If the presented directory is a file package, the system calls the presentedItemDidChange method if your delegate does not implement this method.

Declaration

Parameters

The original URL of the item inside the presented directory. The item need not be at the top level of the presented directory but may itself be inside a nested subdirectory.

newURL

The new URL for the item. This URL may or may not be located inside the presented directory.

Discussion

This method is relevant for applications that present directories. This might occur if the delegate manages the contents of a directory or manages a file that is implemented as a file package. Your implementation of this method should take whatever actions necessary to handle the change in location of the specified item. For example, you might update references to the item in your application’s data structures and refresh your user interface.

If the presented directory is a file package, the system calls the presentedItemDidChange method if your delegate does not implement this method.

Declaration

Parameters

url

The URL of the item in the presented directory that changed. The item need not be at the top level of the presented directory but may itself be inside a nested subdirectory.

Discussion

This method is relevant for applications that present directories. This might occur if the delegate manages the contents of a directory or manages a file that is implemented as a file package. Your implementation of this method should take whatever actions necessary to handle the change in content or attributes of the specified item.

If the presented directory is a file package, the system calls the presentedItemDidChange method if your delegate does not implement this method.