Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何从iCloud中删除文件而不首先将其下载到设备?_Ios_Cocoa Touch_Icloud_Nsfilemanager - Fatal编程技术网

Ios 如何从iCloud中删除文件而不首先将其下载到设备?

Ios 如何从iCloud中删除文件而不首先将其下载到设备?,ios,cocoa-touch,icloud,nsfilemanager,Ios,Cocoa Touch,Icloud,Nsfilemanager,我有一个基本的iOS应用程序,可以显示文档列表。我试图删除一个文档,但注意到如果文档尚未从iCloud下载到设备上,下面的代码将失败,并显示“没有这样的文件或目录” 文档可能相当大(40MB),我希望避免下载文档只是为了删除它(这需要用户的数据计划之外的时间和带宽)。这可能吗 [[[NSFileCoordinator alloc] initWithFilePresenter:nil] coordinateWritingItemAtURL:documentURL

我有一个基本的iOS应用程序,可以显示文档列表。我试图删除一个文档,但注意到如果文档尚未从iCloud下载到设备上,下面的代码将失败,并显示“没有这样的文件或目录”

文档可能相当大(40MB),我希望避免下载文档只是为了删除它(这需要用户的数据计划之外的时间和带宽)。这可能吗

[[[NSFileCoordinator alloc] initWithFilePresenter:nil]
coordinateWritingItemAtURL:documentURL
                  options:NSFileCoordinatorWritingForDeleting
         writingItemAtURL:previewURL
                  options:NSFileCoordinatorWritingForDeleting
                    error:&error
               byAccessor:^(NSURL *newDocumentURL, NSURL *newPreviewURL){

    // Fails with "No such file" error if not yet downloaded from iCloud:
    [[NSFileManager defaultManager] removeItemAtURL:newDocumentURL error:&error];
    [[NSFileManager defaultManager] removeItemAtURL:newPreviewURL  error:&error];
}];
完整错误:

Error Domain=NSCocoaErrorDomain Code=4 "The operation couldn’t be completed. 
(Cocoa error 4.)" UserInfo=0x14e82930 {NSUnderlyingError=0x14e69220 
"The operation couldn’t be completed. No such file or directory",

如果您只需要删除一个文件,请使用另一个NSFileCoordinator CoordinateWritingItemAttribute(在访问器块中有一个新URL参数的文件)

如果需要批量删除,则创建NSFileAccessIntent数组并使用NSFileCoordinator的coordinateAccessWithIntents

例如:

- ( void )deleteItemsAtURLs: ( NSArray * )urls queue: ( NSOperationQueue * )queue
{
    //assuming urls is an array of urls to be deleted
    NSFileCoordinator   * coordinator;
    NSMutableArray      * writingIntents;
    NSURL               * url;

    writingIntents = [ NSMutableArray arrayWithCapacity: urls.count ];

    for( url in urls )
    {
        [ writingIntents addObject: [ NSFileAccessIntent writingIntentWithURL: url options: NSFileCoordinatorWritingForDeleting ] ];
    }

    coordinator = [ [ NSFileCoordinator alloc ] initWithFilePresenter: nil ];

    [ coordinator coordinateAccessWithIntents: writingIntents
                                        queue: queue
                                   byAccessor: ^( NSError * error )
     {
         if( error )
         {
             //handle
             return;
         }
         NSFileAccessIntent * intent;

         error = nil;

         for( intent in writingIntents )
         {
             [ [ NSFileManager defaultManager ] removeItemAtURL: intent.URL error: &error ];
             if( error )
             {
                 //handle
             }
         }
     }];
}
注意:苹果过去有一些示例代码来说明这一点,但可惜的是,它已经被删除了

正如答案中所指出的,您需要在循环中调用此方法,因为您需要为每个要删除的文件指定一个单独的
NSFileCoordinator

我遗漏了一点,那就是您必须调用
fileManager.removitemature
,使用您为删除而创建的
NSFileAccessIntent
对象的URL,而不是从
NSMetadataQueryItem
访问的普通
URL

func removeFile(at url: URL, completionHandler: ((Error?) -> Void)? = nil) {
    // `url` may be a security scoped resource.
    let successfulSecurityScopedResourceAccess = url.startAccessingSecurityScopedResource()

    let fileCoordinator = NSFileCoordinator()
    let writingIntent = NSFileAccessIntent.writingIntent(with: url, options: .forDeleting)
    fileCoordinator.coordinate(with: [writingIntent], queue: backgroundQueue) { (accessError) in
        if accessError != nil {
            completionHandler?(accessError)
            return
        }

        let fileManager = FileManager()
        var error: Error?
        do {
            try fileManager.removeItem(at: writingIntent.url)
        }
        catch let fileError {
            error = fileError
        }
        if successfulSecurityScopedResourceAccess {
            url.stopAccessingSecurityScopedResource()
        }

        completionHandler?(error)
    }
}
如果要删除多个项目:

for url in urlsToDelete {
    removeFile(at: url)
}

事实上,一个接一个地删除它们确实有效。因此,我想这是NSFileCoordinator在尝试同时删除2个文件时出现的错误?您使用的方法不是用于批量删除,而是用于后续操作。有关批处理操作,请参见我给您的示例。不过,我不完全清楚为什么只删除这两项是行不通的。为什么2012年的答案包含IOS8API?如果有与iOS7兼容的解决方案就好了。这解决了我删除由另一台设备创建的iCloud文件的问题。NSFileManager无法单独完成此操作--需要包装在NSFileCoordinator中+1.