当然,在 IOS 的限制下应用只能获取当前进程自身的内存信息。Google 了一阵后,发现大部分博客讲的都是 Object-C 如何获取内存信息,而我这边是用 Swift 开发的,于是尝试将 Object-C 的实现改为 Swift 实现,在此过程中遇到一些坑,记录一下。
IOS 使用 Object-C 实现获取内存信息
大致思路就是利用 task_info
系统接口来实现,我们可以参考 滴滴开源的 DoraemonKit 的实现
#include <mach/mach.h>
+ (NSInteger)useMemoryForApp{
task_vm_info_data_t vmInfo;
mach_msg_type_number_t count = TASK_VM_INFO_COUNT;
kern_return_t kernelReturn = task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &vmInfo, &count);
if(kernelReturn == KERN_SUCCESS)
{
int64_t memoryUsageInByte = (int64_t) vmInfo.phys_footprint;
return (NSInteger)(memoryUsageInByte/1024/1024);
}
else
{
return -1;
}
}
//设备总的内存
+ (NSInteger)totalMemoryForDevice{
return (NSInteger)([NSProcessInfo processInfo].physicalMemory/1024/1024);
}
能看到,其实就是调用了 task_info() 获取到当前进程的信息,第一个参数为当前进程的 mach port,第二个参数是 TASK_VM_INFO,后面两个参数为返回值将引用传进去。
然后获取 task_vm_info_data_t 中的 phys_footprint 就是当前进程的内存占用单位是 byte,在 腾讯开源的 Matrix 也是差不多的实现。
感兴趣的小伙伴可以深入了解一下 task_info() 的实现。
IOS 使用 Swift 实现获取内存信息
按道理来说,这都有 Object-C 的代码了,将它改成 Swift 的实现不是就好了吗?我刚开始也是这么想的…先看看我处理好后的代码吧。
/// 获取内存使用情况
/// - Returns:
/// - used: 已使用
/// - total: 总内存
public static func memoryUsage() -> (used: UInt64, total: UInt64) {
var taskInfo = task_vm_info_data_t()
var count = mach_msg_type_number_t(MemoryLayout<task_vm_info>.size) / 4
let result: kern_return_t = withUnsafeMutablePointer(to: &taskInfo) {
$0.withMemoryRebound(to: integer_t.self, capacity: 1) {
task_info(mach_task_self_, task_flavor_t(TASK_VM_INFO), $0, &count)
}
}
var used: UInt64 = 0
if result == KERN_SUCCESS {
used = UInt64(taskInfo.phys_footprint)
}
let total = ProcessInfo.processInfo.physicalMemory
return (used, total)
}
首先 TASK_VM_INFO_COUNT 常量找不到,这里使用 mach_msg_type_number_t(MemoryLayout<task_vm_info>.size) / 4 方式处理。
还有就是调用 task_info 时,需要使用 withMemoryRebound 来处理 task_vm_info_data_t 指针。
最后我这边是返回了总内存和当前进程已使用内存的元组。