在编写iOS应用时,我们都会大量把服务器的接口调用数据或者图片数据进行缓存,为了更好的使用体验,有时候我们也会把各种缓存的数据所占的空间大小告诉用户,提供给用户参考,并让用户可以手动清除缓存数据,就像我们在千寻影视中也就提供了这样一个设置项。但是当数据多了之后,就会发现所占空间的大小计算非常耗时,因为缓存下来的是大量的小文件,这就会造成界面很久没有反映的状况。为了解决这种情况,当然是可以通过多线程的方法来做到的,但是在一个简单的设置界面做这么复杂的事情,我倒认为是一个拿起牛刀来杀鸡的行为了。本篇就是来探求一些优化手段,把目录的大小计算耗时降到可以接受的程度。
首先,在iOS当中,要实现一个功能,肯定想到去找objective-c的官方库中是否提供了相关功能,如果有,那就直接用objective-c代码来实现了,通过搜索,很容易就写出这样一个函数:
+ (long long) fileSizeAtPath:(NSString*) filePath{
NSFileManager* manager = [NSFileManager defaultManager];
if ([manager fileExistsAtPath:filePath]){
return [[manager attributesOfItemAtPath:filePath error:nil] fileSize];
}
return 0;
}
简单可行,但是,我们这里探讨性能,要优化,很容易想到直接使用c代码,跳过objective-c的封装来做,于是,我们这个函数就变成了:
+ (long long) fileSizeAtPath:(NSString*) filePath{
struct stat st;
if(lstat([filePath cStringUsingEncoding:NSUTF8StringEncoding], &st) == 0){
return st.st_size;
}
return 0;
}
循环1000次,我们就可以发现两者之间巨大的性能差距了,在我的测试环境中,结果如下,c函数的耗时仅是第一种方法的5%
2011-12-31 14:17:22.165 otest[85861:903] [0.041] 使用NSFileManager获取文件大小
2011-12-31 14:17:22.168 otest[85861:903] [0.002] 使用unix c函数获取文件大小
要获取一个目录的总大小,我们就可以写这么一个函数了:
// 循环调用fileSizeAtPath来获取一个目录所占空间大小
+ (long long) folderSizeAtPath2:(NSString*) folderPath{
NSFileManager* manager = [NSFileManager defaultManager];
if (![manager fileExistsAtPath:folderPath]) return 0;
NSEnumerator *childFilesEnumerator = [[manager subpathsAtPath:folderPath] objectEnumerator];
NSString* fileName;
long long folderSize = 0;
while ((fileName = [childFilesEnumerator nextObject]) != nil){
NSString* fileAbsolutePath = [folderPath stringByAppendingPathComponent:fileName];
folderSize += [self fileSizeAtPath:fileAbsolutePath];
}
return folderSize;
}
但是,通过测试,目录遍历本身所带来的时间消耗大大的弱化了我们改进过的fileSizeAtPath函数所带来的优势,导致后者的测试耗时仅是前者的1/2到1/3之间:
2011-12-31 14:17:23.233 otest[85861:903] [0.932] 使用subpathsAtPath然后循环调用NSFileManager获取目录总大小
2011-12-31 14:17:23.582 otest[85861:903] [0.348] 使用subpathsAtPath然后循环调用unix c函数获取目录总大小
既然文件大小的获取可以使用c函数,那么目录的遍历当然可以使用c函数来进行的了,一不做二不休,继续修改优化,代码我就不在继续贴了,附件中有包含了自动测试的整个项目文件,优化后,最终的效果如下:
2011-12-31 14:29:08.520 otest[87180:903] [0.915] 使用subpathsAtPath然后循环调用NSFileManager获取目录总大小
2011-12-31 14:29:08.860 otest[87180:903] [0.339] 使用subpathsAtPath然后循环调用unix c函数获取目录总大小
2011-12-31 14:29:08.953 otest[87180:903] [0.092] 使用纯unix c递归获取目录总大小
项目源代码文件下载点击这里
本篇转自我自己的个人博客站 iOS中使用c函数快速获取一个目录所占的空间大小
分享到:
相关推荐
要获取iOS设备的内存使用情况,可以使用`Darwin`库中的`sysctl`函数。通过查询`kern.memorystatus`结构体,可以获取总内存、空闲内存等数据。在Objective-C中,这通常需要C语言的接口来实现。 4. **磁盘空间**: ...
SQLite是一个嵌入式的SQL数据库引擎,无需单独的服务器进程,可以直接在应用程序中使用。它的优点包括小巧、快速、可靠,以及支持事务处理,这使得它成为iOS开发中的首选数据库。 在iOS中使用SQLite,我们需要引入`...
这个压缩包包含了一个Python脚本,通过分析Xcode工程文件,能够快速检测出iOS项目中未被调用的方法,进而帮助开发者进行代码清理。 首先,我们来了解什么是“未使用的方法”。在iOS项目中,随着时间的推移,开发者...
在描述中提到,回调使用了Block(Block是Objective-C中的一种闭包类型),这是一种轻量级的回调机制,可以方便地在代码中嵌入回调函数,提高代码的可读性和灵活性。Block的使用意味着开发者可以在下载过程中处理各种...
在iOS开发中,UI设计和用户体验是至关重要的部分。`TLTagsControl` 是一款专为iOS平台设计的高效、易用的标签...总之,`TLTagsControl` 是一个强大且实用的工具,对于提高iOS应用的开发效率和用户体验具有显著的帮助。
- **前向声明**:在类声明中仅声明一个实例变量或方法的存在,而不提供其实现细节。 - **懒加载**:只在首次请求时才初始化实例变量,以节省资源。 #### 10. NSCache与NSMutableDictionary - **NSCache**:提供了一...
3. 示例代码:通过提供的示例代码快速理解如何在项目中使用这个库。 4. 文档和API:查看库的文档,了解其提供的API和方法,以便正确使用。 5. 更新和维护:关注库的更新,确保其稳定性和修复已知问题。 6. 性能优化...
OpenCV(开源计算机视觉库)是一个强大的图像处理和计算机视觉库,主要由C/C++语言编写,同时也提供了Python、Java等其他语言的接口。它的设计目标是实现实时的图像处理,广泛应用于机器学习、机器人视觉、图像分析...
这种设计旨在提供一个直观且吸引人的用户体验,让用户能够快速浏览和选择最近的图片。 在实现"iOS最近照片气泡弹窗"时,开发者通常会用到Objective-C(OC)语言,因为这是iOS早期主要的编程语言,虽然Swift现在更为...
源码的实现基于Objective-C或Swift语言,可能是为了方便iOS开发人员快速集成到自己的应用中,以提供类似Photoshop的颜色选择功能。这种颜色拾取器能够帮助用户精确地获取屏幕上的任何像素颜色,并将其转换为各种颜色...
- **原理**: 使用哈希函数将键映射到值的位置上,提供快速查找能力。 - **实现**: `NSDictionary` 是 iOS 开发中常用的哈希表实现之一。 - **应用场景**: 存储和检索键值对。 #### 二、iOS核心概念 **1. 代理模式*...
- **函数定义**:示例代码中的`bubbleSort`函数接收一个整型数组和数组长度作为参数,并在内部实现冒泡排序。 ```objective-c void bubbleSort(int array[], int n) { // 实现冒泡排序 } ``` - **函数调用**:...
本文档旨在为初学者提供一个全面且深入的Objective-C语言入门指南,特别是对于那些想要在iOS平台上进行应用程序开发的学习者来说,这将是一个非常有价值的资源。 #### XCode、Objective-C、Cocoa - **XCode**:...
在iOS应用开发中,缓存管理是至关重要的一个环节,它涉及到应用性能、用户体验以及存储空间的有效利用。本文将深入探讨如何使用一行代码实现iOS应用的缓存计算和清除功能,这对于优化应用性能和减少用户设备存储占用...
`@objc` 表明类型或方法可以在Objective-C环境中使用,`dynamic` 则表示一个方法将在运行时查找。 #### 可选协议和协议扩展 Swift支持可选协议,这意味着协议的某些方法可以是可选的。协议扩展则允许向现有协议...
- **导出符号**: 使用`__declspec(dllexport)`关键字标记需要导出的函数和数据,确保它们可以在其他应用程序中使用。 - **头文件**: 创建包含DLL接口声明的头文件,供其他项目引用。 - **测试与调试**: 编译并...
为了在 C++ 中使用 Protobuf,首先需要定义一个 `.proto` 文件来描述数据结构。例如: ```protobuf message Person { required string name = 1; required int32 id = 2; optional string email = 3; enum ...
- 例如,一个接受两个参数 `a` 和 `b` 的函数可以被转化为一个接受参数 `a` 的函数,该函数返回一个接受参数 `b` 的函数。 - Swift 支持这种函数转换,使得函数可以更灵活地被组合和传递。 2. **将 Protocol 的...
或者在GCD中使用`dispatch_group_notify`或`dispatch_barrier_async`等方法来控制线程的结束。 9. **项目架构与MVC模式**: - MVC(Model-View-Controller)是iOS开发中常用的设计模式,它将应用分为三个部分:...