2015-03-24 3 views
1

Кто-нибудь успешно реализовал «открытое» действие для расширения приложения поставщика файлов? Я дошел до того, что смог прочитать файл, когда пользователь изначально выбирает файл в расширении набора документов (по сути, это действие «импорт»). Но что-то за этим не удается. Вот проблемы, с которыми я столкнулся:Реализация UIDocumentPickerModeOpen с поставщиками файлов

  • Случаи подключения, если я использую NSFileCoordinator.
  • Если я сохраню URL и попытаюсь либо прочитать, либо написать ему позже, вызов startAccessingSecurityScopedResource возвращает NO.Это работает, если я использую закладки.
  • Если я пытаюсь bookmarkDataWithOptions:, я вернусь Error Domain = NSCocoaErrorDomain Code = 260 "Операция не может быть завершена. (Cocoa ошибка 260.)".Это работает, если я создаю закладки внутри области безопасности.

Вот шаблон, который создается для startProvidingItemAtURL: при создании расширения поставщика файла:

- (void)startProvidingItemAtURL:(NSURL *)url completionHandler:(void (^)(NSError *))completionHandler { 
    // Should ensure that the actual file is in the position returned by URLForItemWithIdentifier:, then call the completion handler 
    NSError* error = nil; 
    __block NSError* fileError = nil; 

    NSData * fileData = [NSData data]; 
    // TODO: get the contents of file at <url> from model 

    [self.fileCoordinator coordinateWritingItemAtURL:url options:0 error:&error byAccessor:^(NSURL *newURL) { 
     [fileData writeToURL:newURL options:0 error:&fileError]; 
    }]; 
    if (error!=nil) { 
     completionHandler(error); 
    } else { 
     completionHandler(fileError); 
    } 
} 

Но расширение тупики, когда я использую координатор файл. Кроме того, в документации для startProvidingItemAtURL: указано «Примечание Не используйте координацию файлов внутри этого метода»., так что я взял его.

В другом приложении, это то, что я делаю, чтобы прочитать этот файл в первый раз, а затем создать закладку для этого:

// Start accessing the security scoped resource. 
[url startAccessingSecurityScopedResource]; 

void (^accessor)(NSURL *) = ^void(NSURL *url) { 
    // If the file is missing, create a default here. This really should be done inside 
    // the FileProvider method startProvidingItemAtURL:. Unfortunately, that method does 
    // not get called unless we use use the file coordinator, which can deadlock the app. 
    if (![url checkResourceIsReachableAndReturnError:nil]) { 
    // TODO: Create a real default file here. 
    [[NSFileManager defaultManager] createFileAtPath:url.path 
              contents:nil 
              attributes:nil]; 
    } 

    // TODO: Do something with this file. 
}; 

#ifdef USE_FILE_COORDINATOR 
NSFileCoordinator *fileCoordinator = [NSFileCoordinator new]; 
[fileCoordinator coordinateReadingItemAtURL:url 
            options:NSFileCoordinatorReadingWithoutChanges 
             error:NULL 
           byAccessor:accessor]; 
#else 
accessor(url); 
#endif 

// Store a bookmark for the url in the defaults so we can use it later. 
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
NSError *error = nil; 
NSURLBookmarkCreationOptions options = 0; 
#ifdef NSURLBookmarkCreationWithSecurityScope 
options |= NSURLBookmarkCreationWithSecurityScope; 
#endif 
NSData *bookmarkData = [url bookmarkDataWithOptions:options 
        includingResourceValuesForKeys:nil 
             relativeToURL:nil 
               error:&error]; 
if (error) { 
    NSLog(@"ERROR: %@", error); 
} 
[defaults setObject:bookmarkData forKey:@"BookmarkDataKey"]; 

// Stop accessing the security scoped resource. 
[url stopAccessingSecurityScopedResource]; 

И, наконец, использовать закладку позже, я делаю следующее:

// Get the bookmark from the defaults file. 
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
NSData *bookmarkData = [defaults objectForKey:@"BookmarkDataKey"]; 
if (bookmarkData) { 
    // Convert the bookmark into a URL. 
    NSError *error; 
    BOOL bookmarkIsStale; 
    NSURLBookmarkResolutionOptions options = NSURLBookmarkResolutionWithoutUI; 
#ifdef NSURLBookmarkResolutionWithSecurityScope 
    options |= NSURLBookmarkResolutionWithSecurityScope; 
#endif 

    NSURL *url = [NSURL URLByResolvingBookmarkData:bookmarkData 
             options:options 
            relativeToURL:nil 
          bookmarkDataIsStale:&bookmarkIsStale 
              error:&error]; 

    // Get the data from the URL. 
    BOOL securitySucceeded = [url startAccessingSecurityScopedResource]; 
    if (securitySucceeded) { 
    NSString *message = [NSString stringWithFormat:@"Random number: #%d", arc4random() % 10000]; 
    NSData *fileData = [NSKeyedArchiver archivedDataWithRootObject:message]; 
    NSError *fileError = nil; 
    [fileData writeToURL:url options:0 error:&fileError]; 

    [url stopAccessingSecurityScopedResource]; 
    } 
} 

Второе приложение также иногда является взаимоблокировками, если я использую координацию файлов. Так что я должен просто не использовать координацию файлов во втором приложении? Проблема в том, что если я не использую координацию файлов, то startProvidingItemAtURL: в расширении File Provider никогда не будет вызван.

Также the documentation says использовать NSURLBookmarkCreationWithSecurityScope, но это не определено для iOS. То же самое касается NSURLBookmarkResolutionWithSecurityScope. Должен ли я просто использовать значения OS X или просто не использовать их?

+0

Пожалуйста, добавьте код, чтобы я мог вам помочь. Поставщик файлов немного сложнее. Даже мы отслеживали его по методам следа и ошибок –

+0

Спасибо за ваш ответ. В конце концов, я думаю, что я заработал, удалив координатор файла и игнорируя константы закладки безопасности в области безопасности. –

+0

Привет, Можете ли вы поделиться простой демонстрацией на github. Спасибо, – Durgaprasad

ответ

2

В конце концов, я думаю, что он работает, удаляя файловую координацию везде и игнорируя константы закладки безопасности.Вот то, что я использовал для startProvidingItemAtURL: в расширении провайдера файла:

- (void)startProvidingItemAtURL:(NSURL *)url completionHandler:(void (^)(NSError *))completionHandler { 
    // If the file doesn't exist then create one. 
    if (![url checkResourceIsReachableAndReturnError:nil]) { 
    __block NSError *fileError = nil; 
    NSString *message = @"This is a test message"; 
    NSData *fileData = [NSKeyedArchiver archivedDataWithRootObject:message]; 
    [fileData writeToURL:url options:0 error:&fileError]; 
    completionHandler(fileError); 
    } 
} 

В другом приложении, это то, что я делаю, чтобы прочитать этот файл в первый раз, а затем создать закладку для этого:

// Start accessing the security scoped resource. 
[url startAccessingSecurityScopedResource]; 

// If the file is missing, create a default here. This really should be done inside 
// the FileProvider method startProvidingItemAtURL:. Unfortunately, that method does 
// not get called unless we use use the file coordinator, which can deadlock the app. 
if (![url checkResourceIsReachableAndReturnError:nil]) { 
    // TODO: Create a real default file here. 
    [[NSFileManager defaultManager] createFileAtPath:url.path 
              contents:nil 
             attributes:nil]; 
// TODO: Do something with this file. 

// Store a bookmark for the url in the defaults so we can use it later. 
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
NSError *error = nil; 
NSURLBookmarkCreationOptions options = 0; 
#ifdef NSURLBookmarkCreationWithSecurityScope 
options |= NSURLBookmarkCreationWithSecurityScope; 
#endif 
NSData *bookmarkData = [url bookmarkDataWithOptions:options 
        includingResourceValuesForKeys:nil 
             relativeToURL:nil 
               error:&error]; 
if (error) { 
    NSLog(@"ERROR: %@", error); 
} 
[defaults setObject:bookmarkData forKey:@"BookmarkDataKey"]; 

// Stop accessing the security scoped resource. 
[url stopAccessingSecurityScopedResource]; 

И, наконец, использовать закладку позже, я делаю следующее:

// Get the bookmark from the defaults file. 
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
NSData *bookmarkData = [defaults objectForKey:@"BookmarkDataKey]; 
if (bookmarkData) { 
    // Convert the bookmark into a URL. 
    NSError *error; 
    BOOL bookmarkIsStale; 
    NSURLBookmarkResolutionOptions options = NSURLBookmarkResolutionWithoutUI; 
#ifdef NSURLBookmarkResolutionWithSecurityScope 
    options |= NSURLBookmarkResolutionWithSecurityScope; 
#endif 

    NSURL *url = [NSURL URLByResolvingBookmarkData:bookmarkData 
             options:options 
            relativeToURL:nil 
          bookmarkDataIsStale:&bookmarkIsStale 
              error:&error]; 

    // Get the data from the URL. 
    BOOL securitySucceeded = [url startAccessingSecurityScopedResource]; 
    if (securitySucceeded) { 
    NSString *message = [NSString stringWithFormat:@"Random number: #%d", arc4random() % 10000]; 
    NSData *fileData = [NSKeyedArchiver archivedDataWithRootObject:message]; 
    NSError *fileError = nil; 
    [fileData writeToURL:url options:0 error:&fileError]; 

    [url stopAccessingSecurityScopedResource]; 
    } 
} 
+0

Вы можете помочь с http://stackoverflow.com/questions/30613645/add-edit-in-exel-or-edit-photo-extension – Durgaprasad

0

Вы не предполагают, чтобы позвонить координатор файла вызовов в: staringProvidingItemsAtUrl
Проверьте яблочные комментарии для метода, и он говорит:
- (void)startProvidingItemAtURL:(NSURL *)url completionHandler:(void (^)(NSError *error))completionHandler
Note
Do not use file coordination inside this method. The system already guarantees that no other process can access the file while this method is executing.

После удаления:
[self.fileCoordinator coordinateWritingItemAtURL:url options:0 error:&error byAccessor:^(NSURL *newURL)
Тупик должны исчезнуть.
Также: NSURLBookmarkCreationWithSecurityScope
не относится к IOS, и IOS не имеет этой опции. Эта опция для IOS не нужна. Яблочный документ ОЧЕНЬ путается в этом.

 Смежные вопросы

  • Нет связанных вопросов^_^