ChatGPT解决这个技术问题 Extra ChatGPT

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

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 space. Following is the snippet of the code which does the job for me:

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

Am I correct with the above snippet? or is there any better way to know total available/free disk space. I've to detect total free disk space, since we've to prevent our application to perform sync in the low disk space scenario.

I hope the stackoverflow link will help you..
It looks like the code he's using in his question is better than the code in the link you have given (he's just checking one directory instead of traversing all sub-directories under "/")
Thanks Mikhail for the link. But I'm looking for total available/free disk space on iPhone/iPad device, not just a particular folder. For example, on a 32GB iPhone, if the total available/free size is 28GB, I should be able to detect that programmatically.
I hope this link helps : jayprakashdubey.blogspot.in/2014/07/…

C
Community

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.


Converting to a float may give inaccurate results above around 2GB. If you need to deal with really large file sizes, use a double or long double instead.
As pointed by Ash, this method has a inaccurate result. In my iPad 2, with 64GB, it fails by +0.25 GB... The method below, posted by David H, has the accurate result when using uint64_t vars.
The code snippet has been edited to reflect suggestions from @David H as shown below.
+200 MB is not a problem. In the Settings I have "0 bytes" available space. And when I enter and use my app, this method reports about 150mb free space. Then I fill up this remaining space and only then the app crashes. So I would say that this method gives you more correct information than what you see in Settings.
Why is no one using NSUInteger instead of stuff like uint64_t ? We're writing Obj-C, not C++ or C. NSUInteger will give you an unsigned 64 bit integer now, but if things happen to change I imagine that Apple will update that Macro (let's say 128 bits at some point, becomes real)
D
David H

Revised source using 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;
}

EDIT: it seems someone edited this code to use 'uint64_t' instead of 'unsigned long long'. While in the foreseeable future this should be just fine, they are not the same. 'uint64_t' is 64 bits and will always be that. In 10 years 'unsigned long long' might be 128. its a small point but why I used unsignedLongLong.


I don't have experience with the new automatic counting system but Whats the __autoreleasing for? You normally don't need to autorelease the NSError returned
on my iPod Touch 4th Gen running iOS 5.1, NSFileSystemFreeSize is still reporting ~200 MBytes too much. I print out the content of the whole NSDictionary in debugger... NSFileSystemSize is correct though... anybody have solution for this problem?
@Zennichimaro: Did you fix your problem? I am also facing the same issue, getting 0.2 GB extra when i check free space in iPad. iPad is showing 24.1 GB available space but in code it is showing 24.3 GB.
@Diejmon you cannot ask NSNumber for an integeral size of this type. This is why for such things I prefer a unit of known bit size. While technically I agree with your statement, I already have enough warnings to deal with using NSInteger and format strings! 64 bits will be enough bits for sure in my lifetime and yours.
C
Cuong Lam

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

https://i.stack.imgur.com/C7gpW.png


Do you have any idea why MBFormatter is there? It's not used anywhere.
MBFormatter is a function to convert any value to MB value. I'm not using it for demo project. But i'm need for other project.
This is great to put in a FileManager extension.
iTunes shows 18.99 GB free but I get 13.41 GB when I use described methods. Does anyone know what I miss?
@CuongLam Unwrapping errors aren't thrown and aren't caught by do/catch. Sample source code should be written to handle errors correctly. stackoverflow.com/questions/34628999/…
0
0x8BADF00D

If you need formatted string with size you can take a look at nice library on 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;
}

To format, one can also use NSBytCounterFormatter
This is still prone to same +200MB bug: stackoverflow.com/questions/9270027/…
C
Christopher Lloyd

Don't use 'unsigned', it is only 32 bits which will overflow past 4GB, which is less than the typical iPad/iPhone free space. Use unsigned long long (or uint64_t), and retrieve the value out of the NSNumber as a 64-bit int too using unsignedLongLongValue.


Its better than a tip - "Its the Law" :-) As he said, the original code is just plain wrong.
C
Community

If your looking to get the the remaining free space using Swift it is slightly different. You need to use attributesOfFileSystemForPath() instead of 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
    }
}

Edit: Updated for Swift 1.0
Edit 2: Updated for safety, using Martin R's answer.
Edit 3: Updated for Swift 2.0 (by dgellow)


I was trying to use this answer, but it won't compile under GM ([NSObject : AnyObject]? does not have a member named 'subscript'). I think this is due the issue raised here but I don't understand how to make that answer work in this context. Any help greatly appreciated.
I updated the answer to work on Swift 1.0 now. Because attributesOfFileSystemForPath returns [NSObject : AnyObject]? you need to cast to NSDictionary? as it could be nil and then unwrap the dictionary in order to subscript it. (That is a bit unsafe, so I'll update the answer a bit latter with a safer solution when I have the time.)
Thanks for the update. As it turns out, about an hour before your reply I had gone ahead and formulated the issue as a fresh question here. There is an answer there now, but since this method of dealing with optionals is a bit opaque to me, I'd love to see another approach at your convenience. Give my regards to your sister Rachel.
Bryan, I would suggest the first answer to your answered question as it is a good mix of safety and clarity. I'm not sure I could give a better answer then that one. Optionals can be a be confusing at first, I strongly suggest reading the Swift manuals section on optionals it is quite good.
Much appreciated, I'll look at that manual again and I've found some good SO questions as well. Bryan
k
kakaiikaka

Update with a new accurate API to get available size on disk available in iOS11. Here is the description for the new API resource key:

#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

https://i.stack.imgur.com/uDeSd.png

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

Where “opportunistic usage” is coming from on your screenshot?
Found it, volumeAvailableCapacityForOpportunisticUsageKey.
Yes rshev, volumeAvailableCapacityForOpportunisticUsageKey gets "“opportunistic usage" on my screenshot
to see the available storage size should I query with NSHomeDirectory() or NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true). Is there any difference using these two?
C
ChrisJF

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.


@JuanBoero Posted in Swift 3.1 (finally)!
a
abdullahselek

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()

Do not use ! instead put a guard to safe typecasting or nil check.
Thanks for your comments @TheTiger.
M
Markus

Important clarification (at least for me). If I connect my iPod to my Mac this is the info showed by iTunes App.

https://i.stack.imgur.com/bMg4Q.jpg

When I use the above code:

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

The countStyle NSByteCountFormatterCountStyleFile show me: 17,41 GB

The countStyle NSByteCountFormatterCountStyleBinary show me: 16,22 GB

16,22 GB (NSByteCountFormatterCountStyleBinary) It is EXACTLY the number that iTunes App show me when I connect my iPod to my Mac.


maybe File is only for MAC files and not iOS?
it's the same amount of byte multiplied as 1000 (KB then MB then GB) versus 1024.
i
ivanzoid

Here is Swift 5 extension for FileManager with proper error handling and no automatic string conversions (convert byte count to string as you prefer). Also follows FileManager's naming.

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

Example usage:

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

R
Robert

For iOS >= 6.0 you can use the new NSByteCountFormatter. This code gets the number of free bytes remaining as a formatted string.

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

K
Kiran Shakya

Following code is Swift 3.0 version implementation of the answer previously provided by ChrisJF:

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

}

Why is that returning more then iPhone' s available disk space information. When iPhones' setup menu says 998MB, that returns 1.2 GB
a
ale_stro

for Swift as UIDevice extension

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

How to use:

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

Output will be:

Memory 9656 of 207694 Mb available.

A
Andrea Mario Lufino

I know this post is a bit old, but I think this answer can help someone. If you want to know the used/free/total disk space on the device you can use Luminous. It's written in Swift. You have only to call :

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

or

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

J
Jivan Bhandari

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.


J
Juan Boero

ChrisJF answer in Swift 2.1 version:

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

}

a
arango_86

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