How to detect total available/free disk space on the iPhone/iPad device?

后端 未结 18 1759
别跟我提以往
别跟我提以往 2020-11-22 11:14

I\'m looking for a better way to detect available/free disk space on the iPhone/iPad device programmatically.
Currently I\'m using the NSFileManager to detect the disk s

相关标签:
18条回答
  • 2020-11-22 11:31

    Swift implementation of above code:-

    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;
        }
    
    
    }
    

    Call it from any other class.

    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");
        }
    

    While testing the returned value, it's same as shown by other apps. At least in my iPhone 6S+. It's just the swift implementation of the above shown answer. And for me the accepted answer didn't work.

    0 讨论(0)
  • 2020-11-22 11:32

    I have written a class to get available/used memory using Swift. Demo at: https://github.com/thanhcuong1990/swift-disk-status
    Swift 4 updated.

    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
            }
        }
    
    }
    

    Demo

    get disk space status with Swift

    0 讨论(0)
  • 2020-11-22 11:33

    If you want to save time, use the following CocoaPod Library. I didn't used it but seems like it should work.

    https://cocoapods.org/pods/SystemServices

    0 讨论(0)
  • 2020-11-22 11:34

    You can find an another solution with using Swift 4 and extension which gives you a good option.

    Here is the UIDevice extension.

    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"
        }
    
    }
    

    And sample usage:

    UIDevice.current.totalDiskSpaceInBytes()
    UIDevice.current.totalDiskSpace()
    UIDevice.current.freeDiskSpaceInBytes()
    UIDevice.current.freeDiskSpace()
    UIDevice.current.usedDiskSpaceInBytes()
    UIDevice.current.usedDiskSpace()
    
    0 讨论(0)
  • 2020-11-22 11:36

    UPDATE: Since a lot of time has passed after this answer and new methods/APIs have been added, please check the updated answers below for Swift etc; Since I've not used them myself, I can't vouch for them.

    Original answer: I found the following solution working for me:

    -(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;
    }
    

    It returns me exactly the size that iTunes displays when device is connected to machine.

    0 讨论(0)
  • 2020-11-22 11:40

    Here's my answer and why it's better.

    Answer (Swift):

    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
    }
    

    Answer (Objective-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;
    }
    

    Why it's better:

    • Utilizes Cocoa's built in library NSByteCountFormatter, meaning no crazy manual calculations from bytes to gigabytes. Apple does this for you!
    • Easily translatable: NSByteCountFormatter does this for you. E.g. When the device's language is set to English the string will read 248.8 MB but will read 248,8 Mo when set to French, et cetera for other languages.
    • A default value is given in case of an error.
    0 讨论(0)
提交回复
热议问题