用Swift查询可用的iOS磁盘空间

我正在尝试使用Swift获取可用的iOS设备存储。 我在这里find了这个函数

  func deviceRemainingFreeSpaceInBytes() -> NSNumber { let documentDirectoryPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) let systemAttributes = NSFileManager.defaultManager().attributesOfFileSystemForPath(documentDirectoryPath.last as String, error: nil) return systemAttributes[NSFileSystemFreeSize] as NSNumber } 

但是在编译时这个错误是给出的: [NSObject : AnyObject]? does not have a member named 'subscript' [NSObject : AnyObject]? does not have a member named 'subscript'我相信这个错误来自这里提到的问题,即attributesOfFileSystemForPath返回一个可选的字典( 文档 )。 我从一般意义上理解这个问题,但是因为build议的解决scheme涉及嵌套的情况,所以我不太清楚如何解决我感兴趣的function(这对Swift来说并不新鲜) 。 有人可以build议如何使function工作? 注意:我不确定原始函数是否由作者testing过,或者它是否在xcode 6testing版下运行,但是根据我看到的,它在GM下不起作用。

可选的绑定if let在这里工作以及。

我会build议该函数返回一个可选的Int64 ,以便它可以返回nil来表示失败:

 func deviceRemainingFreeSpaceInBytes() -> Int64? { let documentDirectoryPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) if let systemAttributes = NSFileManager.defaultManager().attributesOfFileSystemForPath(documentDirectoryPath.last as String, error: nil) { if let freeSize = systemAttributes[NSFileSystemFreeSize] as? NSNumber { return freeSize.longLongValue } } // something failed return nil } 

Swift 2.1更新:

 func deviceRemainingFreeSpaceInBytes() -> Int64? { let documentDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).last! guard let systemAttributes = try? NSFileManager.defaultManager().attributesOfFileSystemForPath(documentDirectory), let freeSize = systemAttributes[NSFileSystemFreeSize] as? NSNumber else { // something failed return nil } return freeSize.longLongValue } 

Swift 3.0更新:

 func deviceRemainingFreeSpaceInBytes() -> Int64? { let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).last! guard let systemAttributes = try? FileManager.default.attributesOfFileSystem(forPath: documentDirectory), let freeSize = systemAttributes[.systemFreeSize] as? NSNumber else { // something failed return nil } return freeSize.int64Value } 

用法:

 if let bytes = deviceRemainingFreeSpaceInBytes() { print("free space: \(bytes)") } else { print("failed") } 

我写了一个类来获得使用Swift的可用内存。 演示在: https : //github.com/thanhcuong1990/swift-disk-status

升级支持Swift 3。

 import UIKit class DiskStatus { //MARK: Formatter MB only class func MBFormatter(_ bytes: Int64) -> String { let formatter = ByteCountFormatter() formatter.allowedUnits = ByteCountFormatter.Units.useMB formatter.countStyle = ByteCountFormatter.CountStyle.decimal formatter.includesUnit = false return formatter.string(fromByteCount: bytes) as String } //MARK: Get String Value class var totalDiskSpace:String { get { return ByteCountFormatter.string(fromByteCount: totalDiskSpaceInBytes, countStyle: ByteCountFormatter.CountStyle.binary) } } class var freeDiskSpace:String { get { return ByteCountFormatter.string(fromByteCount: freeDiskSpaceInBytes, countStyle: ByteCountFormatter.CountStyle.binary) } } class var usedDiskSpace:String { get { return ByteCountFormatter.string(fromByteCount: usedDiskSpaceInBytes, countStyle: ByteCountFormatter.CountStyle.binary) } } //MARK: Get raw value class var totalDiskSpaceInBytes:Int64 { get { do { let systemAttributes = try FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory() as String) let space = (systemAttributes[FileAttributeKey.systemSize] as? NSNumber)?.int64Value return space! } catch { return 0 } } } class var freeDiskSpaceInBytes:Int64 { get { do { let systemAttributes = try FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory() as String) let freeSpace = (systemAttributes[FileAttributeKey.systemFreeSize] as? NSNumber)?.int64Value return freeSpace! } catch { return 0 } } } class var usedDiskSpaceInBytes:Int64 { get { let usedSpace = totalDiskSpaceInBytes - freeDiskSpaceInBytes return usedSpace } } } 

演示:

用Swift获取磁盘空间状态

这与Martin对Swift 3.1的回答相似,但转换为UIDevice的扩展,使访问更容易。

 extension UIDevice { var systemSize: Int64? { guard let systemAttributes = try? FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory() as String), let totalSize = (systemAttributes[.systemSize] as? NSNumber)?.int64Value else { return nil } return totalSize } var systemFreeSize: Int64? { guard let systemAttributes = try? FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory() as String), let freeSize = (systemAttributes[.systemFreeSize] as? NSNumber)?.int64Value else { return nil } return freeSize } } 

获得自由空间:

 UIDevice.current.systemFreeSize 

并获得总空间:

 UIDevice.current.systemSize 

那么,根据上面的代码:

 let usedSpace = totalDiskSpaceInBytes - freeDiskSpaceInBytes 

您可能会发现usedSpace不等于iPhone设置页面的值。 这是因为在iOS11中,Apple 为“重要”资源引入了总可用容量(以字节为单位)

“重要”资源的总可用容量(以字节为单位),包括预期通过清除非必需资源和caching资源来清除的空间。 “重要”是指用户或应用程序明确期望在本地系统上存在的东西,但最终可以replace。 这将包括用户通过UI显式请求的项目,以及应用程序为了提供function而需要的资源。

示例:用户明确请求观看但尚未完成观看的video或用户请求下载的audio文件。

这个值不应该用来确定是否有空间存在不可替代的资源。 在不可替代的资源的情况下,总是尝试保存资源,不pipe可用的容量,并尽可能优雅地处理失败。

为了得到与我们在iPhone设置页面中看到的完全相同的值,我们可以通过volumeAvailableCapacityForImportantUsage获得可用空间

 if let space = try? URL(fileURLWithPath: NSHomeDirectory() as String).resourceValues(forKeys: [URLResourceKey.volumeAvailableCapacityForImportantUsageKey]).volumeAvailableCapacityForImportantUsage { return space ?? 0 } 

您可以使用以下UIDevice扩展名 :

Swift4

 extension UIDevice { func MBFormatter(_ bytes: Int64) -> String { let formatter = ByteCountFormatter() formatter.allowedUnits = ByteCountFormatter.Units.useMB formatter.countStyle = ByteCountFormatter.CountStyle.decimal formatter.includesUnit = false return formatter.string(fromByteCount: bytes) as String } //MARK: Get String Value var totalDiskSpaceInGB:String { return ByteCountFormatter.string(fromByteCount: totalDiskSpaceInBytes, countStyle: ByteCountFormatter.CountStyle.decimal) } var freeDiskSpaceInGB:String { return ByteCountFormatter.string(fromByteCount: freeDiskSpaceInBytes, countStyle: ByteCountFormatter.CountStyle.decimal) } var usedDiskSpaceInGB:String { return ByteCountFormatter.string(fromByteCount: usedDiskSpaceInBytes, countStyle: ByteCountFormatter.CountStyle.decimal) } var totalDiskSpaceInMB:String { return MBFormatter(totalDiskSpaceInBytes) } var freeDiskSpaceInMB:String { return MBFormatter(freeDiskSpaceInBytes) } var usedDiskSpaceInMB:String { return MBFormatter(usedDiskSpaceInBytes) } //MARK: Get raw value var totalDiskSpaceInBytes:Int64 { guard let systemAttributes = try? FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory() as String), let space = (systemAttributes[FileAttributeKey.systemSize] as? NSNumber)?.int64Value else { return 0 } return space } /* Total available capacity in bytes for "Important" resources, including space expected to be cleared by purging non-essential and cached resources. "Important" means something that the user or application clearly expects to be present on the local system, but is ultimately replaceable. This would include items that the user has explicitly requested via the UI, and resources that an application requires in order to provide functionality. Examples: A video that the user has explicitly requested to watch but has not yet finished watching or an audio file that the user has requested to download. This value should not be used in determining if there is room for an irreplaceable resource. In the case of irreplaceable resources, always attempt to save the resource regardless of available capacity and handle failure as gracefully as possible. */ var freeDiskSpaceInBytes:Int64 { if #available(iOS 11.0, *) { if let space = try? URL(fileURLWithPath: NSHomeDirectory() as String).resourceValues(forKeys: [URLResourceKey.volumeAvailableCapacityForImportantUsageKey]).volumeAvailableCapacityForImportantUsage { return space ?? 0 } else { return 0 } } else { if let systemAttributes = try? FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory() as String), let freeSpace = (systemAttributes[FileAttributeKey.systemFreeSize] as? NSNumber)?.int64Value { return freeSpace } else { return 0 } } } var usedDiskSpaceInBytes:Int64 { return totalDiskSpaceInBytes - freeDiskSpaceInBytes } } 

用法:

 Logger.d("totalDiskSpaceInBytes: \(UIDevice.current.totalDiskSpaceInBytes)") Logger.d("freeDiskSpace: \(UIDevice.current.freeDiskSpaceInBytes)") Logger.d("usedDiskSpace: \(UIDevice.current.usedDiskSpaceInBytes)") 

在这里输入图像说明