我正在尝试使用iOS获得可用的Swift
设备存储。我找到了这个函数这里
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'
--我相信这个错误是由提到的这里问题引起的,即attributesOfFileSystemForPath
返回一个可选字典(文档)。我从一般意义上理解这个问题,但由于建议的解决方案涉及嵌套的情况,所以我不太明白如何修复我感兴趣的函数(这无助于我对Swift
非常陌生)。有人能建议如何使这个功能发挥作用吗?注意:我不确定最初的函数是由作者测试的,还是在xcode 6测试版下运行的,但据我所知,它在GM下不起作用。
发布于 2014-10-04 23:29:09
iOS 11更新
下面给出的答案在iOS 11下不再提供准确的结果。有一些新的卷容量键可以传递给URL.resourceValues(forKeys:)
,提供与设备设置中可用的值相匹配的值。
static let volumeAvailableCapacityKey: URLResourceKey
键(只读)。static let volumeAvailableCapacityForImportantUsageKey: URLResourceKey
键(只读)。static let volumeAvailableCapacityForOpportunisticUsageKey: URLResourceKey
键。static let volumeTotalCapacityKey: URLResourceKey
键。来自苹果的文档
概述 在尝试在本地存储大量数据之前,首先验证您是否有足够的存储容量。要获得卷的存储容量,可以构造一个URL (使用URL实例),该URL引用要查询的卷上的对象,然后查询该卷。 决定使用哪种查询类型 要使用的查询类型取决于存储的内容。如果您根据用户请求或应用程序正常工作所需的资源存储数据(例如,用户将要观看的视频或游戏中下一级所需的资源),则使用
volumeAvailableCapacityForImportantUsageKey
查询。但是,如果您正在以更有预见性的方式下载数据(例如,下载用户最近一直在看的电视剧中的一集),请查询volumeAvailableCapacityForOpportunisticUsageKey
。 构造查询 使用此示例作为指南构建您自己的查询:
let fileURL = URL(fileURLWithPath: NSHomeDirectory() as String)
do {
let values = try fileURL.resourceValues(forKeys: [.volumeAvailableCapacityForImportantUsageKey])
if let capacity = values.volumeAvailableCapacityForImportantUsage {
print("Available capacity for important usage: \(capacity)")
} else {
print("Capacity is unavailable")
}
} catch {
print("Error retrieving capacity: \(error.localizedDescription)")
}
原始答案
与if let
的可选绑定在这里也同样有效。
我建议函数返回一个可选的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
}
SWIFT2.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
}
SWIFT3.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")
}
发布于 2017-11-23 22:09:44
好吧,根据上面的代码:
let usedSpace = totalDiskSpaceInBytes - freeDiskSpaceInBytes
您可能会发现,usedSpace并不等于iPhone设置页面的值。这是因为在iOS11中,苹果为“重要”资源引入了以字节为单位的总可用容量。
“重要”资源的总可用容量(以字节为单位),包括通过清除非必需资源和缓存资源来清除的空间。“重要”是指用户或应用程序显然希望在本地系统中出现的东西,但最终是可替换的。这将包括用户通过UI明确请求的项,以及应用程序提供功能所需的资源。示例:用户明确请求观看但尚未完成观看的视频或用户请求下载的音频文件。此值不应用于确定是否存在不可替代资源的空间。对于不可替代的资源,无论可用容量如何,总是尝试保存资源,并尽可能优雅地处理故障。
为了获得与我们在volumeAvailableCapacityForImportantUsage设置页面中所看到的完全相同的值,我们可以通过iPhone获得空闲空间。
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
}
}
用法:
print("totalDiskSpaceInBytes: \(UIDevice.current.totalDiskSpaceInBytes)")
print("freeDiskSpace: \(UIDevice.current.freeDiskSpaceInBytes)")
print("usedDiskSpace: \(UIDevice.current.usedDiskSpaceInBytes)")
发布于 2015-04-02 16:28:05
我编写了一个类,以便使用Swift获得可用/使用的内存。演示at: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
}
}
}
演示:
https://stackoverflow.com/questions/26198073
复制相似问题