菜鸟教程小白 发表于 2022-12-12 14:49:01

ios - 使用文件提供程序实现 UIDocumentPickerModeOpen


                                            <p><p>是否有人为文件提供程序应用扩展成功实现了“打开”操作?当用户最初在文档选择器扩展中选择文件时,我已经能够读取文件(本质上,这是“导入”操作)。但除此之外的任何事情都失败了。以下是我遇到的问题:</p>

<ul>
<li>如果我使用 <code>NSFileCoordinator</code>,应用程序会死锁。</li>
<li><del>如果我保存 URL 并稍后尝试读取或写入它,对 <code>startAccessingSecurityScopedResource</code> 的调用将返回 <code>NO</code>。</del> <strong>如果我使用书签,这将有效。</strong></li>
<li><del>如果我尝试 <code>bookmarkDataWithOptions:</code>,我会返回 <em>Error Domain=NSCocoaErrorDomain Code=260 "The operation could not be completed. (Cocoa error 260.)"</em>.</del> <strong>如果我在安全范围内创建书签,这将有效。</strong></li>
</ul>

<p>这是在创建文件提供程序扩展时为 <code>startProvidingItemAtURL:</code> 创建的模板:</p>

<pre><code>- (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 = ;
    // TODO: get the contents of file at &lt;url&gt; from model

    [self.fileCoordinator coordinateWritingItemAtURL:url options:0 error:&amp;error byAccessor:^(NSURL *newURL) {
      ;
    }];
    if (error!=nil) {
      completionHandler(error);
    } else {
      completionHandler(fileError);
    }
}
</code></pre>

<p>但是当我使用文件协调器时,扩展会死锁。此外,<code>startProvidingItemAtURL:</code> 的文档说 <em>"<strong>Note</strong>
不要在这个方法中使用文件协调。”</em> 所以我把它拿出来了。</p>

<p>在另一个应用程序中,这是我第一次读取该文件然后为其创建书签的操作:</p>

<pre><code>// Start accessing the security scoped resource.
;

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 (!) {
    // TODO: Create a real default file here.
    [ createFileAtPath:url.path
                                          contents:nil
                                          attributes:nil];
}

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

#ifdef USE_FILE_COORDINATOR
NSFileCoordinator *fileCoordinator = ;
[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 = ;
NSError *error = nil;
NSURLBookmarkCreationOptions options = 0;
#ifdef NSURLBookmarkCreationWithSecurityScope
options |= NSURLBookmarkCreationWithSecurityScope;
#endif
NSData *bookmarkData = [url bookmarkDataWithOptions:options
                     includingResourceValuesForKeys:nil
                                    relativeToURL:nil
                                                error:&amp;error];
if (error) {
NSLog(@&#34;ERROR: %@&#34;, error);
}
;

// Stop accessing the security scoped resource.
;
</code></pre>

<p>最后,为了稍后使用书签,我正在执行以下操作:</p>

<pre><code>// Get the bookmark from the defaults file.
NSUserDefaults *defaults = ;
NSData *bookmarkData = ;
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:&amp;bookmarkIsStale
                                           error:&amp;error];

// Get the data from the URL.
BOOL securitySucceeded = ;
if (securitySucceeded) {
    NSString *message = ;
    NSData *fileData = ;
    NSError *fileError = nil;
    ;

    ;
}
}
</code></pre>

<p>如果我使用文件协调,第二个应用程序有时也会死锁。那么我是否也应该不在第二个应用程序中使用文件协调?问题是,如果我不使用文件协调,那么文件提供程序扩展中的 <code>startProvidingItemAtURL:</code> 似乎永远不会被调用。</p>

<p>另外,<a href="https://developer.apple.com/library/ios/documentation/FileManagement/Conceptual/DocumentPickerProgrammingGuide/CreatinganOutstandingUserExperience/CreatinganOutstandingUserExperience.html" rel="noreferrer noopener nofollow">the documentation says</a>使用 <code>NSURLBookmarkCreationWithSecurityScope</code> 但这对于 iOS 是未定义的。 <code>NSURLBookmarkResolutionWithSecurityScope</code> 也是如此。我应该只使用 OS X 值还是不使用它们? </p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>最后,我认为我已经通过在各处删除文件协调并忽略安全范围书签常量来使其正常工作。这是我在文件提供程序扩展中用于 <code>startProvidingItemAtURL:</code> 的内容:</p>

<pre><code>- (void)startProvidingItemAtURL:(NSURL *)url completionHandler:(void (^)(NSError *))completionHandler {
// If the file doesn&#39;t exist then create one.
if (!) {
    __block NSError *fileError = nil;
    NSString *message = @&#34;This is a test message&#34;;
    NSData *fileData = ;
    ;
    completionHandler(fileError);
}
}
</code></pre>

<p>在另一个应用程序中,这是我第一次读取该文件然后为其创建书签的操作:</p>

<pre><code>// Start accessing the security scoped resource.
;

// 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 (!) {
// TODO: Create a real default file here.
[ 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 = ;
NSError *error = nil;
NSURLBookmarkCreationOptions options = 0;
#ifdef NSURLBookmarkCreationWithSecurityScope
options |= NSURLBookmarkCreationWithSecurityScope;
#endif
NSData *bookmarkData = [url bookmarkDataWithOptions:options
                     includingResourceValuesForKeys:nil
                                    relativeToURL:nil
                                                error:&amp;error];
if (error) {
NSLog(@&#34;ERROR: %@&#34;, error);
}
;

// Stop accessing the security scoped resource.
;
</code></pre>

<p>最后,为了稍后使用书签,我正在执行以下操作:</p>

<pre><code>// Get the bookmark from the defaults file.
NSUserDefaults *defaults = ;
NSData *bookmarkData = ;
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:&amp;bookmarkIsStale
                                           error:&amp;error];

// Get the data from the URL.
BOOL securitySucceeded = ;
if (securitySucceeded) {
    NSString *message = ;
    NSData *fileData = ;
    NSError *fileError = nil;
    ;

    ;
}
}
</code></pre></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 使用文件提供程序实现 UIDocumentPickerModeOpen,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/29242732/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/29242732/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 使用文件提供程序实现 UIDocumentPickerModeOpen