UIDocumentPickerViewController NewBox App Hangs

I mean WWDC 2014 NewBox sample application for document provider extension. I am using the following code from a NeBox app to import a document from a document provider into my app.

- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentAtURL:(NSURL *)url {
BOOL startAccessingWorked = [url startAccessingSecurityScopedResource];
NSURL *ubiquityURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
NSLog(@"ubiquityURL %@",ubiquityURL);
NSLog(@"start %d",startAccessingWorked);

NSFileCoordinator *fileCoordinator = [[NSFileCoordinator alloc] init];
NSError *error;
[fileCoordinator coordinateReadingItemAtURL:url options:0 error:&error byAccessor:^(NSURL *newURL) {
    NSData *data = [NSData dataWithContentsOfURL:newURL];
    NSLog(@"error %@",error);
    NSLog(@"data %@",data);
}];
[url stopAccessingSecurityScopedResource]; 

      

}

The app hangs completely for the coordReadingItemAtURL method. Any inputs would be helpful.

+3


source to share


4 answers


I noticed this problem in the NewBox application as well, and decided to trace it. So, there are two extensions in this application: Document Picker and File Provider. In short, there is a race condition between the two when they try to access files in the application's document storage folder.

In my opinion, the easiest way to trace the problem is to put NSLog()

in a bunch of locations. However, the problem is that the debug output generated by the extension won't show up in the Xcode console. The good news is that you can open the console in the iOS Simulator app by clicking the Debug → Open System Log menu. This will show all sorts of debug messages, including those generated by extensions. Read more about advanced debugging here .

Using this method, you can easily understand that execution loops over the File Provider method startProvidingItemAtURL

. More specifically, the following line is deadlocked:

[self.fileCoordinator coordinateWritingItemAtURL:url options:0 error:&error byAccessor:^(NSURL *newURL) {

      



Why? Take a look at the documentation for coordinateWritingItemAtURL

:

If the url parameter specifies a file: This method expects other readers and writers of the same file to complete actions in the process.

The function documentPicker

you mentioned invokes a read operation, which in turn invokes a write operation. This is a dead end. I think the easiest way to fix this is to avoid being used coordinateWritingItemAtURL

in the file provider.

+1


source


According to the documentation:



Each of these methods synchronously waits on the same thread they were called on before invoking the access block on the same thread, instead of waiting asynchronously and scheduling the block to be called on a specific queue.

0


source


Apple recommends against using file coordination inside this method. The system already guarantees that no other process can access the file while this method is running. This is the only reason for this impasse.

See this documentation for details .

0


source


You can also use a block. The unit is running too fast, the freeze issue will be resolved.

Step 1: Take a Global Variable

UIDocumentPickerViewController *documentPicker; 

      

also decalre

typedef void(^myCompletion)(BOOL);

      

Step 2: Write a way in which allocation happens and can send a callback on completion

-(void) allocateDocumentPicker:(myCompletion) compblock{
    //do stuff
    documentPicker = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:@[@"public.content"]
                                                                            inMode:UIDocumentPickerModeImport];
    documentPicker.delegate = self;
    documentPicker.modalPresentationStyle = UIModalPresentationFormSheet;
    compblock(YES);
}

      

Step 3: Call a method in which allocation occurs every time you want to open composer, but present it as YES when completed.

-(IBAction)attachmentButtonClicked:(id)sender{

    [self allocateDocumentPicker:^(BOOL finished) {
        if(finished){
            [self.parentScreen presentViewController:documentPicker animated:YES completion:nil];
        }
    }];
}

      

Simple syntax to create your own block, refer to the link from this link Custom completion block for my own method

0


source







All Articles