如何检测iPhone / iPad设备上的总可用/可用磁盘空间?


147

我正在寻找一种更好的方法来以编程方式检测iPhone / iPad设备上的可用/可用磁盘空间。
目前,我正在使用NSFileManager来检测磁盘空间。以下是对我有用的代码片段:

-(unsigned)getFreeDiskspacePrivate {
NSDictionary *atDict = [[NSFileManager defaultManager] attributesOfFileSystemForPath:@"/" error:NULL];
unsigned freeSpace = [[atDict objectForKey:NSFileSystemFreeSize] unsignedIntValue];
NSLog(@"%s - Free Diskspace: %u bytes - %u MiB", __PRETTY_FUNCTION__, freeSpace, (freeSpace/1024)/1024);

return freeSpace;
}


我对以上代码片段正确吗?还是有更好的方法来了解总的可用/可用磁盘空间。
我必须检测总的可用磁盘空间,因为我们必须防止应用程序在磁盘空间不足的情况下执行同步。


我希望stackoverflow链接将对您有所帮助
。–

1
看来他在问题中使用的代码比您提供的链接中的代码更好(他只是检查一个目录,而不是遍历“ /”下的所有子目录)
Kendall Helmstetter Gelner 2011年

感谢Mikhail提供的链接。但是我正在寻找iPhone / iPad设备上的总可用/可用磁盘空间,而不仅仅是一个特定的文件夹。例如,在32GB的iPhone上,如果总的可用/可用大小为28GB,我应该能够以编程方式检测到该大小。
Code.Warrior 2011年

我希望此链接对您有所
Jayprakash Dubey

Answers:


152

更新:由于在此答案之后已经花费了很多时间,并且添加了新的方法/ API,因此请在下面查看Swift等更新的答案;由于我自己没有使用过它们,因此我不能担保它们。

原始答案:我发现以下解决方案对我有用:

-(uint64_t)getFreeDiskspace {
    uint64_t totalSpace = 0;
    uint64_t totalFreeSpace = 0;
    NSError *error = nil;  
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);  
    NSDictionary *dictionary = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[paths lastObject] error: &error];  

    if (dictionary) {  
        NSNumber *fileSystemSizeInBytes = [dictionary objectForKey: NSFileSystemSize];  
        NSNumber *freeFileSystemSizeInBytes = [dictionary objectForKey:NSFileSystemFreeSize];
        totalSpace = [fileSystemSizeInBytes unsignedLongLongValue];
        totalFreeSpace = [freeFileSystemSizeInBytes unsignedLongLongValue];
        NSLog(@"Memory Capacity of %llu MiB with %llu MiB Free memory available.", ((totalSpace/1024ll)/1024ll), ((totalFreeSpace/1024ll)/1024ll));
    } else {  
        NSLog(@"Error Obtaining System Memory Info: Domain = %@, Code = %ld", [error domain], (long)[error code]);
    }  

    return totalFreeSpace;
}

当设备连接到计算机时,它可以准确返回iTunes显示的大小。


4
转换为浮点数可能会导致2GB以上的结果不准确。如果您需要处理很大的文件,请改用double或long double。
灰烬2012年

正如Ash指出的那样,该方法的结果不准确。在我的iPad 2(64GB)中,它失败了+0.25 GB。...由David H发布的以下方法在使用uint64_t vars时具有准确的结果。
Leandro Alves 2012年

3
该代码段已被编辑,以反映来自@David H的建议,如下所示。
Code.Warrior 2012年

4
+200 MB没问题。在“设置”中,我有“ 0字节”的可用空间。当我输入并使用我的应用程序时,此方法报告了约150mb的可用空间。然后我填满了剩余的空间,然后应用程序崩溃了。因此,我想说的是,此方法比“设置”中提供的信息更正确。
ancajic 2015年

4
为什么没有人使用NSUInteger而不是类似的东西uint64_t?我们正在编写Obj-C,而不是C ++或C。NSUInteger现在将为您提供一个无符号的64位整数,但是如果事情发生了变化,我想苹果公司将更新Macro(在某个时候说128位,变为真实)。
Goles

59

使用unsigned long long修改源代码:

- (uint64_t)freeDiskspace
{
    uint64_t totalSpace = 0;
    uint64_t totalFreeSpace = 0;

    __autoreleasing NSError *error = nil;  
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);  
    NSDictionary *dictionary = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[paths lastObject] error: &error];  

    if (dictionary) {  
        NSNumber *fileSystemSizeInBytes = [dictionary objectForKey: NSFileSystemSize];  
        NSNumber *freeFileSystemSizeInBytes = [dictionary objectForKey:NSFileSystemFreeSize];
        totalSpace = [fileSystemSizeInBytes unsignedLongLongValue];
        totalFreeSpace = [freeFileSystemSizeInBytes unsignedLongLongValue];
        NSLog(@"Memory Capacity of %llu MiB with %llu MiB Free memory available.", ((totalSpace/1024ll)/1024ll), ((totalFreeSpace/1024ll)/1024ll));
    } else {  
        NSLog(@"Error Obtaining System Memory Info: Domain = %@, Code = %d", [error domain], [error code]);  
    }  

    return totalFreeSpace;
}

编辑:似乎有人编辑了此代码以使用'uint64_t'而不是'unsigned long long'。虽然在可预见的将来这应该很好,但它们并不相同。'uint64_t'是64位,并且将始终如此。在10年中,“ unsigned long long”可能是128。这是一个小问题,但是为什么我使用unsignedLongLong。


我没有使用新的自动计数系统的经验,但是__autoreleasing有何用途?你通常不需要自动释放的NSError返回
牧师


3
在运行iOS 5.1的iPod Touch第四代上,NSFileSystemFreeSize仍然报告约200 MBytes。我在调试器中打印出整个NSDictionary的内容... NSFileSystemSize是正确的,但是...有人对此问题有解决方案吗?
Zennichimaro

@Zennichimaro:您解决了问题吗?我也面临着同样的问题,当我检查iPad中的可用空间时会额外获得0.2 GB的空间。iPad显示24.1 GB的可用空间,但在代码中显示24.3 GB。
Sudheer Kumar Palchuri 2013年

1
@Diejmon,您不能要求NSNumber提供这种类型的整数。这就是为什么在这种情况下,我更喜欢使用已知位大小的单位。从技术上讲,我同意您的声明,但我已经有足够的警告来处理NSInteger和格式化字符串!64位将足以确保我和您的一生。
David H

34

我已经编写了一个类来使用Swift获取可用/已使用的内存。演示位于:https : //github.com/thanhcuong1990/swift-disk-status
Swift 4已更新。

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.file)
        }
    }

    class var freeDiskSpace:String {
        get {
            return ByteCountFormatter.string(fromByteCount: freeDiskSpaceInBytes, countStyle: ByteCountFormatter.CountStyle.file)
        }
    }

    class var usedDiskSpace:String {
        get {
            return ByteCountFormatter.string(fromByteCount: usedDiskSpaceInBytes, countStyle: ByteCountFormatter.CountStyle.file)
        }
    }


    //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获取磁盘空间状态


您知道为什么会有MBFormatter吗?它没有在任何地方使用。
本·辛克莱

MBFormatter是将任何值转换为MB值的函数。我没有将其用于演示项目。但是我需要其他项目。
崇林2015年

1
放入FileManager扩展非常好。
里昂,

2
iTunes显示18.99 GB的可用空间,但是使用上述方法时,我可以获得13.41 GB的空间。有人知道我想念什么吗?
Vitalii Boiarskyi

1
@CuongLam不会引发展开错误,也不会被do / catch捕获。应该编写示例源代码以正确处理错误。stackoverflow.com/questions/34628999/…–
SafeFastExpressive

26

如果您需要格式化的字符串和大小,可以在GitHub上查看漂亮的库

#define MB (1024*1024)
#define GB (MB*1024)

@implementation ALDisk

#pragma mark - Formatter

+ (NSString *)memoryFormatter:(long long)diskSpace {
    NSString *formatted;
    double bytes = 1.0 * diskSpace;
    double megabytes = bytes / MB;
    double gigabytes = bytes / GB;
    if (gigabytes >= 1.0)
        formatted = [NSString stringWithFormat:@"%.2f GB", gigabytes];
    else if (megabytes >= 1.0)
        formatted = [NSString stringWithFormat:@"%.2f MB", megabytes];
    else
        formatted = [NSString stringWithFormat:@"%.2f bytes", bytes];

    return formatted;
}

#pragma mark - Methods

+ (NSString *)totalDiskSpace {
    long long space = [[[[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:nil] objectForKey:NSFileSystemSize] longLongValue];
    return [self memoryFormatter:space];
}

+ (NSString *)freeDiskSpace {
    long long freeSpace = [[[[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:nil] objectForKey:NSFileSystemFreeSize] longLongValue];
    return [self memoryFormatter:freeSpace];
}

+ (NSString *)usedDiskSpace {
    return [self memoryFormatter:[self usedDiskSpaceInBytes]];
}

+ (CGFloat)totalDiskSpaceInBytes {
    long long space = [[[[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:nil] objectForKey:NSFileSystemSize] longLongValue];
    return space;
}

+ (CGFloat)freeDiskSpaceInBytes {
    long long freeSpace = [[[[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:nil] objectForKey:NSFileSystemFreeSize] longLongValue];
    return freeSpace;
}

+ (CGFloat)usedDiskSpaceInBytes {
    long long usedSpace = [self totalDiskSpaceInBytes] - [self freeDiskSpaceInBytes];
    return usedSpace;
}

2
要进行格式化,还可以使用NSBytCounterFormatter
Daniel Barden

这仍然是倾向于同一+ 200MB错误:stackoverflow.com/questions/9270027/...
Paulius Liekis

13

不要使用“无符号”,只有32位会溢出4GB,这比典型的iPad / iPhone可用空间要少。使用unsigned long long(或uint64_t),并也使用unsignedLongLongValue从NSNumber作为64位int检索值。


3
它比技巧更好-“ Its the Law” :-)正如他所说,原始代码完全是错误的。
David H

13

如果您希望使用Swift获得剩余的可用空间,则略有不同。您需要使用attributesOfFileSystemForPath()而不是attributesOfItemAtPath():

func deviceRemainingFreeSpaceInBytes() -> Int64? {
    let documentDirectoryPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
    var attributes: [String: AnyObject]
    do {
        attributes = try NSFileManager.defaultManager().attributesOfFileSystemForPath(documentDirectoryPath.last! as String)
        let freeSize = attributes[NSFileSystemFreeSize] as? NSNumber
        if (freeSize != nil) {
            return freeSize?.longLongValue
        } else {
            return nil
        }
    } catch {
        return nil
    }
}

编辑:为Swift 1.0更新。
编辑2:为安全起见,使用Martin R的答案进行了更新
编辑3:已为Swift 2.0更新(由dgellow


我正在尝试使用此答案,但无法在GM下编译([NSObject:AnyObject]?没有名为'subscript'的成员)。我认为这是由于此处提出的问题引起的但是我不明白如何在这种情况下使该答案起作用。任何帮助,不胜感激。
布莱恩·汉森

我更新了答案,现在可以在Swift 1.0上工作了。因为attributeOfFileSystemForPath返回[NSObject:AnyObject]?您需要转换为NSDictionary吗?因为它可能为零,然后解开字典以对其下标。(这有点不安全,所以我有时间的时候再用更安全的解决方案来更新答案。)
RubenSandwich 2014年

感谢更新。事实证明,在您答复之前大约一个小时,我在这里将问题重新提出。现在有一个答案,但是由于这种处理可选内容的方法对我来说有点不透明,我希望在您方便的时候再看看另一种方法。向您的姐姐瑞秋致以我的问候。
布莱恩·汉森

Bryan,我建议您回答问题的第一个答案,因为它既安全又清晰。我不确定我能给出一个更好的答案。可选选项一开始可能会令人困惑,我强烈建议您阅读Swift手册中有关可选选项的部分,这是相当不错的。
RubenSandwich 2014年

非常感谢,我将再次查看该手册,并且发现一些很好的SO问题。Bryan
Bryan Hanson 2014年

9

这是我的答案,为什么会更好。

答案(快速):

func remainingDiskSpaceOnThisDevice() -> String {
    var remainingSpace = NSLocalizedString("Unknown", comment: "The remaining free disk space on this device is unknown.")
    if let attributes = try? FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory()),
        let freeSpaceSize = attributes[FileAttributeKey.systemFreeSize] as? Int64 {
        remainingSpace = ByteCountFormatter.string(fromByteCount: freeSpaceSize, countStyle: .file)
    }
    return remainingSpace
}

答案(目标C):

- (NSString *)calculateRemainingDiskSpaceOnThisDevice
{
    NSString *remainingSpace = NSLocalizedString(@"Unknown", @"The remaining free disk space on this device is unknown.");
    NSDictionary *dictionary = [[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:nil];
    if (dictionary) {
        long long freeSpaceSize = [[dictionary objectForKey:NSFileSystemFreeSize] longLongValue];
        remainingSpace = [NSByteCountFormatter stringFromByteCount:freeSpaceSize countStyle:NSByteCountFormatterCountStyleFile];
    }
    return remainingSpace;
}

为什么更好:

  • 利用Cocoa的内置库NSByteCountFormatter,这意味着从字节到千兆字节都不会进行疯狂的手动计算。苹果为您做到这一点!
  • 轻松翻译:NSByteCountFormatter为您做到这一点。例如,当设备的语言设置为英语时,该字符串将读取248.8 MB,但在设置为法语等其他语言时,该字符串将显示248,8Mo。
  • 发生错误时将提供默认值。

1
@JuanBoero最终发布在Swift 3.1中!
克里斯·JF,2017年

7

重要的说明(至少对我来说)。如果我将iPod连接到Mac,这就是iTunes App显示的信息。

iTunes应用程序中的iPod内存信息

当我使用上面的代码时:

long long freeSpace = [[[[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:nil]
                            objectForKey:NSFileSystemFreeSize] longLongValue];

NSString *free1 = [NSByteCountFormatter stringFromByteCount:freeSpace countStyle:NSByteCountFormatterCountStyleFile];

[label1 setText:free1];

NSString *free2 = [NSByteCountFormatter stringFromByteCount:freeSpace countStyle:NSByteCountFormatterCountStyleBinary];

[label2 setText:free2];

countStyle NSByteCountFormatterCountStyleFile向我展示:17,41 GB

countStyle NSByteCountFormatterCountStyleBinary向我展示:16,22 GB

16,22 GBNSByteCountFormatterCountStyleBinary)是EXACTLY是iTunes应用程序告诉我,当我在我的iPod连接到我的Mac数量。


也许文件仅适用于MAC文件而不适用于iOS?
若奥·努涅斯

它乘以1000(KB然后再MB GB)与1024相同数量字节
Jim75

7

使用新的准确API更新,以获取iOS11中可用磁盘上的可用大小。这是新API资源密钥的描述:

#if os(OSX) || os(iOS)
/// 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.
@available(OSX 10.13, iOS 11.0, *) @available(tvOS, unavailable) @available(watchOS, unavailable)
public var volumeAvailableCapacityFor Usage: Int64? { return _get(.volumeAvailableCapacityForImportantUsageKey) }
#endif

我交叉比较了键“ FileAttributeKey.systemFreeSize ”和键“ URLResourceKey.volumeAvailableCapacityForImportantUsageKey ”的结果,发现从“ volumeAvailableCapacityForImportantUsageKey ” 返回的结果与UI上显示的可用存储完全匹配。 可用磁盘空间比较 这是快速的实现:

class var freeDiskSpaceInBytesImportant:Int64 {
    get {
        do {
            return try URL(fileURLWithPath: NSHomeDirectory() as String).resourceValues(forKeys: [URLResourceKey.volumeAvailableCapacityForImportantUsageKey]).volumeAvailableCapacityForImportantUsage!
        } catch {
            return 0
        }
    }
}

屏幕快照中的“机会性用法”来自哪里?
rshev '17

找到了volumeAvailableCapacityForOpportunisticUsageKey
rshev '17

是rshev,volumeAvailableCapacityForOpportunisticUsageKey在我的屏幕截图上显示为“机会性用法”
Evilisn Jiang

查看可用存储空间,我应该使用NSHomeDirectory()或查询NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)。使用这两者有什么区别吗?
Suryakant Sharma

7

你可以找到与使用另一种解决方案斯威夫特4extension它给你一个不错的选择。

这是UIDevice扩展名。

extension UIDevice {

    func totalDiskSpaceInBytes() -> Int64 {
        do {
            guard let totalDiskSpaceInBytes = try FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory())[FileAttributeKey.systemSize] as? Int64 else {
                return 0
            }
            return totalDiskSpaceInBytes
        } catch {
            return 0
        }
    }

    func freeDiskSpaceInBytes() -> Int64 {
        do {
            guard let totalDiskSpaceInBytes = try FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory())[FileAttributeKey.systemFreeSize] as? Int64 else {
                return 0 
            }
            return totalDiskSpaceInBytes
        } catch {
            return 0
        }
    }

    func usedDiskSpaceInBytes() -> Int64 {
        return totalDiskSpaceInBytes() - freeDiskSpaceInBytes()
    }

    func totalDiskSpace() -> String {
        let diskSpaceInBytes = totalDiskSpaceInBytes()
        if diskSpaceInBytes > 0 {
            return ByteCountFormatter.string(fromByteCount: diskSpaceInBytes, countStyle: ByteCountFormatter.CountStyle.binary)
        }
        return "The total disk space on this device is unknown"
    }

    func freeDiskSpace() -> String {
        let freeSpaceInBytes = freeDiskSpaceInBytes()
        if freeSpaceInBytes > 0 {
            return ByteCountFormatter.string(fromByteCount: freeSpaceInBytes, countStyle: ByteCountFormatter.CountStyle.binary)
        }
        return "The free disk space on this device is unknown"
    }

    func usedDiskSpace() -> String {
        let usedSpaceInBytes = totalDiskSpaceInBytes() - freeDiskSpaceInBytes()
        if usedSpaceInBytes > 0 {
            return ByteCountFormatter.string(fromByteCount: usedSpaceInBytes, countStyle: ByteCountFormatter.CountStyle.binary)
        }
        return "The used disk space on this device is unknown"
    }

}

和示例用法:

UIDevice.current.totalDiskSpaceInBytes()
UIDevice.current.totalDiskSpace()
UIDevice.current.freeDiskSpaceInBytes()
UIDevice.current.freeDiskSpace()
UIDevice.current.usedDiskSpaceInBytes()
UIDevice.current.usedDiskSpace()

不要使用!,而不是把guard安全typecastingnil检查。
TheTiger

感谢您的评论@TheTiger。
abdullahselek '18

3

对于iOS> = 6.0,可以使用new NSByteCountFormatter。此代码获取保留为格式化字符串的可用字节数。

NSError *error = nil;
NSArray * const paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSDictionary * const pathAttributes = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[paths firstObject] error:&error];
NSAssert(pathAttributes, @"");
NSNumber * const fileSystemSizeInBytes = [pathAttributes objectForKey: NSFileSystemFreeSize];
const long long numberOfBytesRemaining = [fileSystemSizeInBytes longLongValue];
NSByteCountFormatter *byteCountFormatter = [[NSByteCountFormatter alloc] init];
NSString *formattedNmberOfBytesRemaining = [byteCountFormatter stringFromByteCount:numberOfBytesRemaining];

2

以下代码是ChrisJF先前提供的答案的Swift 3.0版本实现:

func freeSpaceInBytes() -> NSString {

    var remainingSpace = NSLocalizedString("Unknown", comment: "The remaining free disk space on this device is unknown.")

    do {
        let dictionary =  try FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory())
        let freeSpaceSize = ((dictionary[FileAttributeKey.systemFreeSize] as AnyObject).longLongValue)!
        remainingSpace = ByteCountFormatter.string(fromByteCount: freeSpaceSize, countStyle: ByteCountFormatter.CountStyle.file)
    }
    catch let error {
        NSLog(error.localizedDescription)
    }

    return remainingSpace as NSString

}

为什么返回比iPhone的可用磁盘空间更多的信息。当iPhone的设置菜单显示998MB时,返回1.2 GB
希望

1

用于Swift作为UIDevice扩展

extension UIDevice {
    func freeDiskspace() -> NSString {
        let failedResult: String = "Error Obtaining System Memory"
        guard let path = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true).last else {
            return failedResult
        }
        do {
            let dictionary = try NSFileManager.defaultManager().attributesOfFileSystemForPath(path)
            if let fileSystemSizeInBytes = dictionary[NSFileSystemSize] as? UInt,
                let freeFileSystemSizeInBytes =     dictionary[NSFileSystemFreeSize] as? UInt {
                    return "Memory \(freeFileSystemSizeInBytes/1024/1024) of \(fileSystemSizeInBytes/1024/1024) Mb available."
            } else {
                    return failedResult
            }
        } catch {
            return failedResult
        }
    }
}

如何使用:

print("\(UIDevice.currentDevice().freeDiskspace())")

输出将是:

Memory 9656 of 207694 Mb available.

1

我知道这篇文章有点老了,但是我认为这个答案可以帮助某人。如果您想知道设备上的已用/可用/总磁盘空间,可以使用Luminous。它是用Swift编写的。您只需致电:

Luminous.System.Disk.freeSpace()
Luminous.System.Disk.usedSpace()

要么

Luminous.System.Disk.freeSpaceInBytes()
Luminous.System.Disk.usedSpaceInBytes()

1

上面代码的Swift实现:

import UIKit

class DiskInformation: NSObject {

    var totalSpaceInBytes: CLongLong = 0; // total disk space
    var totalFreeSpaceInBytes: CLongLong = 0; //total free space in bytes

    func getTotalDiskSpace() -> String { //get total disk space
        do{
        let space: CLongLong = try FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory())[FileAttributeKey.systemSize] as! CLongLong; //Check for home dirctory and get total system size
            totalSpaceInBytes = space; // set as total space
            return memoryFormatter(space: space); // send the total bytes to formatter method and return the output

        }catch let error{ // Catch error that may be thrown by FileManager
            print("Error is ", error);
        }
        return "Error while getting memory size";
    }

    func getTotalFreeSpace() -> String{ //Get total free space
        do{
            let space: CLongLong = try FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory())[FileAttributeKey.systemFreeSize] as! CLongLong;
            totalFreeSpaceInBytes = space;
            return memoryFormatter(space: space);

        }catch let error{
            print("Error is ", error);
        }
        return "Error while getting memory size";
    }

    func getTotalUsedSpace() -> String{ //Get total disk usage from above variable
        return memoryFormatter(space: (totalSpaceInBytes - totalFreeSpaceInBytes));
    }

    func memoryFormatter(space : CLongLong) -> String{ //Format the usage to return value with 2 digits after decimal
        var formattedString: String;

        let totalBytes: Double = 1.0 * Double(space);
        let totalMb: Double = totalBytes / (1024 * 1024);
        let totalGb: Double = totalMb / 1024;
        if (totalGb > 1.0){
            formattedString = String(format: "%.2f", totalGb);
        }else if(totalMb >= 1.0){
            formattedString = String(format: "%.2f", totalMb);
        }else{
            formattedString = String(format: "%.2f", totalBytes);
        }
        return formattedString;
    }


}

从其他任何类调用它。

func getDiskInfo(){
        let diskInfo = DiskInformation();
        print("Total disk space is", diskInfo.getTotalDiskSpace(),"Gb");
        print("Total free space is", diskInfo.getTotalFreeSpace(),"Gb");
        print("Total used space is", diskInfo.getTotalUsedSpace(),"Gb");
    }

测试返回值时,它与其他应用程序显示的相同。至少在我的iPhone 6S +中。这只是上面显示的答案的快速实现。对我来说,被接受的答案是行不通的。


0

Swift 2.1版本中的ChrisJF答案:

func freeSpaceInBytes() -> NSString{

    var remainingSpace = NSLocalizedString("Unknown", comment: "The remaining free disk space on this device is unknown.")

    do {

        let dictionary =  try NSFileManager.defaultManager().attributesOfFileSystemForPath(NSHomeDirectory())
        freeSpaceSize = (dictionary[NSFileSystemFreeSize]?.longLongValue)!
        remainingSpace = NSByteCountFormatter.stringFromByteCount(freeSpaceSize, countStyle: NSByteCountFormatterCountStyle.File)

    }
    catch let error as NSError {

        error.description
        NSLog(error.description)

    }

    return remainingSpace

}


0

Swift 5扩展,可FileManager进行适当的错误处理,并且不会自动进行字符串转换(可以根据需要将字节数转换为字符串)。也遵循FileManager的命名。

extension FileManager {
    func systemFreeSizeBytes() -> Result<Int64, Error> {
        do {
            let attrs = try attributesOfFileSystem(forPath: NSHomeDirectory())
            guard let freeSize = attrs[.systemFreeSize] as? Int64 else {
                return .failure(NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey : "Can't retrieve system free size"]))
            }
            return .success(freeSize)
        } catch {
            return .failure(error)
        }
    }

    func systemSizeBytes() -> Result<Int64, Error> {
         do {
             let attrs = try attributesOfFileSystem(forPath: NSHomeDirectory())
             guard let size = attrs[.systemSize] as? Int64 else {
                 return .failure(NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey : "Can't retrieve system size"]))
             }
             return .success(size)
         } catch {
             return .failure(error)
         }
     }
}

用法示例:

let freeSizeResult = FileManager.default.systemFreeSizeBytes()
switch freeSizeResult {
case .failure(let error):
    print(error)
case .success(let freeSize):
    let freeSizeString = ByteCountFormatter.string(fromByteCount: freeSize, countStyle: .file)
    print("free size: \(freeSizeString)")
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.