2014-09-03 33 views
3

我指的是WWDC 2014示例应用NewBox文档提供商扩展。 我正在使用NeBox应用程序的以下代码,将文档从Document Provider导入到我的应用程序。UIDocumentPickerViewController NewBox应用挂起

- (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]; 

}

应用完全挂起coordinateReadingItemAtURL方法。 任何输入都会有帮助。

回答

0

作为每文档:

每种方法同步等待它们调用的传入的同一个线程上存取块,而不是异步等待和调度调用之前被调用的相同的线程上阻止特定队列。

1

我在NewBox应用中也注意到了这个问题,并决定跟踪它。所以,这个应用程序中有两个扩展:文档选取器和文件提供器。长话短说,当他们尝试访问应用程序的文档存储文件夹中的文件时,两者之间存在竞争状态。

在我看来,最容易找出问题的方法是将NSLog()放在一堆地点。但问题是,扩展生成的调试输出在Xcode控制台中不可见。好消息是,您可以点击Debug→Open System Log菜单,打开iOS模拟器应用程序中的控制台。这将显示各种调试消息,包括由扩展生成的消息。你可以找到更多关于扩展调试here

通过使用这种方法,人们可以很容易地意识到执行卡在文件提供程序的方法startProvidingItemAtURL中。更具体地说,以下行导致死锁:

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

这是为什么?看看文档coordinateWritingItemAtURL

如果url参数指定一个文件: 此方法等待其他读者和完全相同的文件的作家完成正在进行的动作。

您提到的函数documentPicker调用了读操作,该操作又触发了写操作。这是一个僵局。我想解决这个问题的最简单方法是避免在文件提供程序中使用coordinateWritingItemAtURL

0

Apple建议您不要在此方法内使用文件协调。系统已经保证在此方法执行时没有其他进程可以访问文件。这是造成这种僵局的唯一原因。

详情请参阅this documentation

1

也可以使用块。 Block工作速度太快,挂起问题会得到解决。

第1步:取

UIDocumentPickerViewController *documentPicker; 

全局变量也decalre

typedef void(^myCompletion)(BOOL); 

第2步:写在那里的分配发生,并且可以在完成

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

发送回调的方法第3步:每次打开作曲者时调用分配的方法,但是在此之前在接收完成时发送它为是。

-(IBAction)attachmentButtonClicked:(id)sender{ 

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

简单的语法创建自己的块,从这个链接 Custom completion block for my own method

采取参考