Long delay with NSFileCoordinator coordinateWritingItemAtURL
Asked Answered
T

2

9

I'm setting up NSFileCoordinator and NSFilePresenter in my app so I can do file IO from my AppleWatch app safely. There are some places in my code where I write to a file a couple of times in quick succession. This is a problem in and of itself and I'm working to correct it, but I'm noticing some weird behavior in the process.

I wrap my writes like this:

//In a class that implements NSFilePresenter:
NSFileCoordinator *coord = [[NSFileCoordinator alloc]initWithFilePresenter:self];
[coord coordinateWritingItemAtURL:self.presentedItemUrl options:0 error:nil byAccessor:^(NSURL *url)
{
  //do my writing here using CFWriteStreamRef or NSOutputStream
}];

On the first write, the write block happens within 1 ms. But after that, there's about a 0.5 second delay between calling coordinateWritingItemAtURL and the write block being executed.

Is this expected behavior?

Some of the documentation for NSFileCoordinator and NSFilePresenter says to use prepareForReadingItemsAtURLs:writingItemsAtURLs:options:error:byAccessor: for batch operations, but it seems weird to get such a long delay when I don't batch.

Update: This happens with reading too.

Update 2: Here is an example project reproducing the problem.

Update 3: Using this API for coordination between an app and its extension is apparently a bad idea. But the question still stands.

Tarkany answered 16/4, 2015 at 15:15 Comment(4)
Where are you calling coordinateWriting... from. The watch Extension, the parent app via openParentApplication, somewhere else...?Outlet
@MattG in the parent application.Tarkany
Pass a valid NSError object in the error field to see if you get any error on the first write (maybe that's why it returns immediately). Other than that, usually, blocks don't execute right away, their behavior is asynchronous and can execute at a later time in the run loop.Miller
I always pass an error, and never get anything back.Tarkany
L
4

Referring to File System Programming Guide , you can read following:

you might want to avoid incorporating changes directly from your file presenter method. Instead, dispatch a block asynchronously to a dispatch queue and process the changes at a later time. This lets you process the changes at your app’s convenience without causing unnecessary delays to the file coordinator that initiated the change. Of course, when saving or relinquishing control of a file (such as in the relinquishPresentedItemToReader:, relinquishPresentedItemToWriter:, or savePresentedItemChangesWithCompletionHandler: methods) you should perform all necessary actions immediately and not defer them.

I think this is your case where you are defering actions.

Possible Solution:

Please read this well , to properly handle multiple successive writing operations , the relinquishPresentedItemToWriter , can do the job , same will work with reading file , relinquishPresentedItemToReader , supposing that multiple different objects are trying to read and write the same file.

P.S :

I dont know what your app does exactly , but i hope you have read this :

If you are implementing a document-based app, you do not need to incorporate file presenter semantics into your NSDocument subclasses. The NSDocument class already conforms to the NSFilePresenter protocol and implements the appropriate methods. Thus, all of your documents automatically register themselves as presenters of their corresponding file and do things like save changes and track changes to the document.

Latinism answered 13/5, 2015 at 4:55 Comment(7)
I'm not using NSDocument. The IO work that is wrapped by the coordinate... methods CFReadStreamRef and CFWriteStreamRef. And I'm not doing anything expensive when relinquishing to other readers/writers. The delay seems to be spent getting ahold of whatever locks are used to coordinate across processes.Tarkany
@Mr.Jefferson are there other objects trying to deal with your file while writing to it ?Latinism
There are multiple file presenters per file, yes. But see the example project. The delay is present in the very trivial example.Tarkany
@Mr.Jefferson let me check ur code n get back to u.Latinism
@Mr.Jefferson i dont have access right now to a device that runs mac OS , can we communicate using teamviewer?? i have to see this code running and debug it on realtime environement.Latinism
No can do, sorry. The bounty won't end for 24 hours after the finish time though.Tarkany
@Mr.Jefferson what has the bounty to do with trying to help you ? :)Latinism
B
3

Is it possible to use options NSFileCoordinatorReadingImmediatelyAvailableMetadataOnly for reading and NSFileCoordinatorWritingContentIndependentMetadataOnly for writing in some cases? Looks like this iOS8 options can help you.

Bodwell answered 12/5, 2015 at 23:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.