在iOS上删除包含大量文件的文件夹的性能

时间:2014-02-28 16:26:48

标签: ios performance delete-file nsfilemanager

假设我的iOS应用程序数据目录中有一个文件夹,其中包含数千个小文件。删除此文件夹(通过[NSFileManager removeItemAtPath])需要花费大量时间。但在OS X上,删除具有相同内容的文件夹非常快。它似乎只是取消文件夹与文件系统的链接。那么为什么iOS需要这么长时间?有什么区别?

编辑:在iPad 3上,删除包含5,000到9,000个文件的3个文件夹大约需要35秒。在较旧的Retina MBP上运行的模拟器上,大约需要1.5秒。

3 个答案:

答案 0 :(得分:5)

  

您看到的层次结构不是“真实的” - 目录   不是它们似乎包含的文件的物理容器。   目录层次结构是一个精心维护的小说。

     

无关紧要:原始的Mac文件系统迈出了一步   进一步 - 它使目录结构完全是一个视觉虚构    - 所有文件都在(3.5“)软盘的根目录下,只有似乎被安排在文件夹中。谢天谢地,这是   被HFS取代。

     

最好将目录/文件夹视为一种特殊的文件   包含将要假装的一组文件的索引   包含。

     

从概念上讲,这与传统的Cocoa内存管理非常相似。   每个(目录/对象)通过引用“拥有”一组(文件/对象)   (“保留”(文件/对象))。

     

从目录中删除文件时,它将被“释放”。如果没有别的   目录对该文件有所有权声明,它是“dealloc'ed”。

     

您的(文件夹/对象)不包含它“拥有”的对象。它   甚至没有“拥有”他们 - 它只是有一个“所有权声明”   它们。

     

来自维基百科关于硬链接的文章:

     
    

“硬链接是一个目录条目,它将名称与文件系统上的文件相关联。目录本身就是一种特殊的文件,     包含此类条目的列表。“

  
     

请注意,由于使用了硬链接,因此可以使用单个链接   可以出现在多个目录中的物理文件。每一个   这些目录拥有对“真实”文件的引用。每个参考   和任何其他人一样“真实”。所有引用都必须“取消链接”   要标记为已删除的文件。

     

“文件”甚至可以在不同的“名称”中有不同的名称   目录!

     

硬链接是文件系统功能的链锯 - 功能强大,但是   可能非常危险。请注意,OSX GUI无法提供   生成硬链接,甚至是符号链接。

来自this email list item

现在关于iOS

[NSFileManager removeItemAtPath:error:],它在它下面做了什么 hood是他们遍历子目录和文件并删除 他们先。这需要一些时间。如果可能,我感兴趣 立即执行此操作,甚至没有隐式递归。只需删除 目录以及文件和子目录会消失吗?

你可以做的是

  1. 如果您担心这会花费时间并且您需要即时结果,您可以重命名该文件夹(这几乎是即时的),然后在后台线程中删除重命名的文件夹及其内容。

  2. 如果时间是约束,请尝试在后台线程中运行删除过程,如果不是问题。

答案 1 :(得分:0)

您是在设备和Mac,模拟器和Mac上进行测试吗?
在第一种情况下,差异是由于硬件,iphone比mac慢。
在第二种情况下,你应该认为这是一个模拟器,所以内部机制可能会以某种方式不同 关于这两个过程,有什么区别?

答案 2 :(得分:0)

不要在主线程上执行长时间运行的任务。考虑您要删除文档目录的所有内容。

- (void) deleteDocumentsDirectoryContents
{
    NSString *folderPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSError *error = nil;
    for (NSString *file in [[NSFileManager defaultManager] contentsOfDirectoryAtPath:folderPath error:&error])
    {
        [[NSFileManager defaultManager] removeItemAtPath:[folderPath stringByAppendingPathComponent:file] error:&error];
    }
}

像这样调用上面的函数。

[self performSelectorInBackground:@selector(deleteDocumentsDirectoryContents) withObject:nil];