Wie erkenne ich den gesamten verfügbaren / freien Speicherplatz auf dem iPhone / iPad-Gerät?


147

Ich suche nach einer besseren Möglichkeit, verfügbaren / freien Speicherplatz auf dem iPhone / iPad-Gerät programmgesteuert zu erkennen.
Derzeit verwende ich den NSFileManager, um den Speicherplatz zu ermitteln. Das Folgende ist der Ausschnitt des Codes, der die Arbeit für mich erledigt:

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


Bin ich mit dem obigen Ausschnitt richtig? oder gibt es eine bessere Möglichkeit, den insgesamt verfügbaren / freien Speicherplatz zu ermitteln?
Ich muss den gesamten freien Speicherplatz ermitteln, da wir verhindern müssen, dass unsere Anwendung im Szenario mit geringem Speicherplatz eine Synchronisierung durchführt.


Ich hoffe, der Stackoverflow-Link wird Ihnen helfen ..
senthilMuthu

1
Es sieht so aus, als ob der Code, den er in seiner Frage verwendet, besser ist als der Code in dem von Ihnen angegebenen Link (er überprüft nur ein Verzeichnis, anstatt alle Unterverzeichnisse unter "/" zu durchlaufen)
Kendall Helmstetter Gelner

Danke Mikhail für den Link. Aber ich suche nach insgesamt verfügbarem / freiem Speicherplatz auf dem iPhone / iPad-Gerät, nicht nur nach einem bestimmten Ordner. Wenn beispielsweise auf einem iPhone mit 32 GB die verfügbare / freie Gesamtgröße 28 GB beträgt, sollte ich dies programmgesteuert erkennen können.
Code.Warrior

Antworten:


152

UPDATE : Da nach dieser Antwort viel Zeit vergangen ist und neue Methoden / APIs hinzugefügt wurden, überprüfen Sie bitte die aktualisierten Antworten unten für Swift usw.; Da ich sie selbst nicht benutzt habe, kann ich nicht für sie bürgen.

Ursprüngliche Antwort : Ich habe festgestellt, dass die folgende Lösung für mich funktioniert:

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

Es gibt mir genau die Größe zurück, die iTunes anzeigt, wenn das Gerät an den Computer angeschlossen ist.


4
Die Konvertierung in einen Float kann zu ungenauen Ergebnissen über etwa 2 GB führen. Wenn Sie mit wirklich großen Dateien arbeiten müssen, verwenden Sie stattdessen ein doppeltes oder langes Doppel.
Ash

Wie Ash ausführt, hat diese Methode ein ungenaues Ergebnis. In meinem iPad 2 mit 64 GB schlägt dies um +0,25 GB fehl ... Die folgende Methode, die von David H veröffentlicht wurde, liefert das genaue Ergebnis, wenn uint64_t vars verwendet wird.
Leandro Alves

3
Das Code-Snippet wurde bearbeitet, um Vorschläge von @David H wie unten gezeigt wiederzugeben.
Code.Warrior

4
+200 MB ist kein Problem. In den Einstellungen habe ich "0 Bytes" verfügbaren Speicherplatz. Und wenn ich meine App betrete und benutze, meldet diese Methode ungefähr 150 MB freien Speicherplatz. Dann fülle ich diesen verbleibenden Platz aus und erst dann stürzt die App ab. Daher würde ich sagen, dass diese Methode Ihnen korrektere Informationen liefert als das, was Sie in den Einstellungen sehen.
ancajic

4
Warum benutzt niemand NSUIntegeranstelle von Sachen wie uint64_t? Wir schreiben Obj-C, nicht C ++ oder C. NSUInteger gibt Ihnen jetzt eine vorzeichenlose 64-Bit-Ganzzahl, aber wenn sich etwas ändert, kann ich mir vorstellen, dass Apple dieses Makro aktualisiert (sagen wir, 128 Bit werden irgendwann real).
Goles

59

Überarbeitete Quelle mit 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;
}

BEARBEITEN: Es scheint, dass jemand diesen Code so bearbeitet hat, dass er 'uint64_t' anstelle von 'unsigned long long' verwendet. Während dies in absehbarer Zeit in Ordnung sein sollte, sind sie nicht dasselbe. 'uint64_t' ist 64 Bit und wird es immer sein. In 10 Jahren könnte 'unsigned long long' 128 sein. Es ist ein kleiner Punkt, aber warum ich unsignedLongLong verwendet habe.


Ich habe keine Erfahrung mit dem neuen automatischen Zählsystem, aber wofür ist das __autoreleasing? Normalerweise müssen Sie den zurückgegebenen NSError nicht automatisch freigeben
den Reverend


3
Auf meinem iPod Touch 4th Gen mit iOS 5.1 meldet NSFileSystemFreeSize immer noch ~ 200 MByte zu viel. Ich drucke den Inhalt des gesamten NSDictionary im Debugger aus ... NSFileSystemSize ist jedoch korrekt ... hat jemand eine Lösung für dieses Problem?
Zennichimaro

@Zennichimaro: Hast du dein Problem behoben? Ich stehe auch vor dem gleichen Problem und bekomme 0,2 GB mehr, wenn ich den freien Speicherplatz auf dem iPad überprüfe. Das iPad zeigt 24,1 GB verfügbaren Speicherplatz an, im Code jedoch 24,3 GB.
Sudheer Kumar Palchuri

1
@Diejmon Sie können NSNumber nicht nach einer ganzzahligen Größe dieses Typs fragen. Deshalb bevorzuge ich für solche Dinge eine Einheit mit bekannter Bitgröße. Obwohl ich Ihrer Aussage technisch zustimme, habe ich bereits genügend Warnungen, um NSInteger zu verwenden und Zeichenfolgen zu formatieren! 64 Bit werden sicher genug Bits in meinem und Ihrem Leben sein.
David H

34

Ich habe eine Klasse geschrieben, um mit Swift verfügbaren / verwendeten Speicher zu erhalten. Demo unter: https://github.com/thanhcuong1990/swift-disk-status
Swift 4 aktualisiert.

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

Holen Sie sich mit Swift den Speicherplatzstatus


Haben Sie eine Idee, warum MBFormatter da ist? Es wird nirgendwo verwendet.
Ben Sinclair

MBFormatter ist eine Funktion zum Konvertieren eines beliebigen Werts in einen MB-Wert. Ich benutze es nicht für Demo-Projekt. Aber ich brauche ein anderes Projekt.
Cuong Lam

1
Dies ist großartig, um eine FileManager-Erweiterung einzufügen.
Leon

2
iTunes zeigt 18,99 GB kostenlos an, aber ich bekomme 13,41 GB, wenn ich die beschriebenen Methoden verwende. Weiß jemand was ich vermisse?
Vitalii Boiarskyi

1
@CuongLam Entpackungsfehler werden nicht ausgelöst und nicht von do / catch abgefangen. Beispielquellcode sollte geschrieben werden, um Fehler korrekt zu behandeln. stackoverflow.com/questions/34628999/…
SafeFastExpressive

26

Wenn Sie einen formatierten String mit Größe benötigen, können Sie sich eine schöne Bibliothek auf GitHub ansehen :

#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
Zum Formatieren kann man auch NSBytCounterFormatter
Daniel Barden

Dies ist immer noch anfällig für den gleichen + 200MB Fehler: stackoverflow.com/questions/9270027/…
Paulius Liekis

13

Verwenden Sie nicht "unsigned", es sind nur 32 Bit, die über 4 GB hinauslaufen, was weniger als der typische freie Speicherplatz für iPad / iPhone ist. Verwenden Sie unsigned long long (oder uint64_t) und rufen Sie den Wert auch mit unsignedLongLongValue als 64-Bit-Int aus der NSNumber ab.


3
Es ist besser als ein Tipp - "Es ist das Gesetz" :-) Wie er sagte, ist der ursprüngliche Code einfach falsch.
David H

13

Wenn Sie den verbleibenden freien Speicherplatz mit Swift nutzen möchten, ist dies etwas anders. Sie müssen AttributeOfFileSystemForPath () anstelle von AttributeOfItemAtPath () verwenden:

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: Aktualisiert für Swift 1.0
Edit 2: Aktualisiert für die Sicherheit, Martin R Antwort mit .
Edit 3: Aktualisiert für Swift 2.0 (von dgellow )


Ich habe versucht, diese Antwort zu verwenden, aber sie wird unter GM nicht kompiliert ([NSObject: AnyObject]? Hat kein Mitglied mit dem Namen 'tiefgestellt'). Ich denke, das liegt an dem hier angesprochenen Problem , aber ich verstehe nicht, wie diese Antwort in diesem Zusammenhang funktioniert. Jede Hilfe sehr geschätzt.
Bryan Hanson

Ich habe die Antwort aktualisiert, um jetzt an Swift 1.0 zu arbeiten. Weil AttributeOfFileSystemForPath [NSObject: AnyObject] zurückgibt? Sie müssen in NSDictionary umwandeln? da es null sein könnte und dann das Wörterbuch auspacken, um es zu unterschreiben. (Das ist ein bisschen unsicher, also werde ich die Antwort etwas später mit einer sichereren Lösung aktualisieren, wenn ich Zeit habe.)
RubenSandwich

Danke für das Update. Wie sich herausstellt, etwa eine Stunde vor Ihrer Antwort hatte ich weg vor und die Frage , wie eine neue Frage formuliert hier . Dort gibt es jetzt eine Antwort, aber da diese Methode des Umgangs mit Optionen für mich etwas undurchsichtig ist, würde ich gerne einen anderen Ansatz für Sie sehen. Grüße deine Schwester Rachel von mir.
Bryan Hanson

Bryan, ich würde die erste Antwort auf Ihre beantwortete Frage vorschlagen, da dies eine gute Mischung aus Sicherheit und Klarheit ist. Ich bin mir nicht sicher, ob ich eine bessere Antwort geben könnte als diese. Optionals können zunächst verwirrend sein. Ich empfehle dringend, den Abschnitt Swift-Handbücher über Optionals zu lesen. Es ist ziemlich gut.
RubenSandwich

Sehr geschätzt, ich werde mir dieses Handbuch noch einmal ansehen und ich habe auch einige gute SO-Fragen gefunden. Bryan
Bryan Hanson

9

Hier ist meine Antwort und warum es besser ist.

Antwort (schnell):

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
}

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

Warum ist es besser:

  • Verwendet die in Cocoa integrierte Bibliothek NSByteCountFormatter, was bedeutet, dass keine verrückten manuellen Berechnungen von Bytes bis Gigabytes erforderlich sind . Apple macht das für Sie!
  • Leicht übersetzbar: NSByteCountFormattererledigt dies für Sie. Wenn beispielsweise die Sprache des Geräts auf Englisch eingestellt ist, wird in der Zeichenfolge 248,8 MB angezeigt, in Französisch jedoch 248,8 Mo, für andere Sprachen usw.
  • Im Fehlerfall wird ein Standardwert angegeben.

1
@ JuanBoero Gepostet in Swift 3.1 (endlich)!
ChrisJF

7

Wichtige Klarstellung (zumindest für mich). Wenn ich meinen iPod an meinen Mac anschließe, werden diese Informationen von der iTunes App angezeigt.

Informationen zum iPod-Speicher über die iTunes-App

Wenn ich den obigen Code verwende:

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

Das countStyle NSByteCountFormatterCountStyleFile zeigt mir: 17,41 GB

Der countStyle NSByteCountFormatterCountStyleBinary zeigt mir: 16,22 GB

16,22 GB ( NSByteCountFormatterCountStyleBinary ) Es ist genau die Nummer, die mir die iTunes App anzeigt , wenn ich meinen iPod an meinen Mac anschließe.


Vielleicht ist Datei nur für MAC-Dateien und nicht für iOS?
João Nunes

Es ist die gleiche Menge an Byte multipliziert mit 1000 (KB, dann MB, dann GB) gegenüber 1024.
Jim75

7

Aktualisieren Sie mit einer neuen genauen API, um die verfügbare Größe auf der Festplatte in iOS11 zu erhalten. Hier ist die Beschreibung für den neuen API-Ressourcenschlüssel:

#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

Ich habe die Ergebnisse von Schlüssel " FileAttributeKey.systemFreeSize " und Schlüssel " URLResourceKey.volumeAvailableCapacityForImportantUsageKey " verglichen und festgestellt, dass die von " volumeAvailableCapacityForImportantUsageKey " zurückgegebenen Ergebnisse genau mit dem auf der Benutzeroberfläche angezeigten verfügbaren Speicher übereinstimmen. Vergleich des verfügbaren freien Speicherplatzes Hier ist die schnelle Implementierung:

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

Woher kommt die „opportunistische Nutzung“ auf Ihrem Screenshot?
Rshev

Fand es , volumeAvailableCapacityForOpportunisticUsageKey.
Rshev

Ja rshev, volumeAvailableCapacityForOpportunisticUsageKey erhält "opportunistische Verwendung" auf meinem Screenshot
Evilisn Jiang

Um die verfügbare Speichergröße zu sehen, sollte ich mit NSHomeDirectory()oder abfragen NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true). Gibt es einen Unterschied bei der Verwendung dieser beiden?
Suryakant Sharma

7

Sie können eine andere Lösung mit der Verwendung finden Swift 4 und extensiondas gibt Ihnen eine gute Option.

Hier ist die UIDeviceErweiterung.

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

}

Und Beispielnutzung:

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

Nicht verwenden, !sondern guardin Sicherheit bringen typecastingoder nilüberprüfen.
TheTiger

Vielen Dank für Ihre Kommentare @TheTiger.
Abdullahselek

3

Für iOS> = 6.0 können Sie das neue verwenden NSByteCountFormatter. Dieser Code erhält die Anzahl der verbleibenden freien Bytes als formatierte Zeichenfolge.

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

Der folgende Code ist die Implementierung der Swift 3.0-Version der zuvor von ChrisJF bereitgestellten Antwort:

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

}

Warum werden dadurch mehr als die verfügbaren Speicherplatzinformationen des iPhones zurückgegeben? Wenn das Setup-Menü des iPhones 998 MB anzeigt, werden 1,2 GB zurückgegeben
Hope

1

für Swift als UIDevice-Erweiterung

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

Wie benutzt man:

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

Ausgabe wird sein:

Memory 9656 of 207694 Mb available.

1

Ich weiß, dass dieser Beitrag etwas alt ist, aber ich denke, diese Antwort kann jemandem helfen. Wenn Sie den verwendeten / freien / gesamten Speicherplatz auf dem Gerät kennen möchten, können Sie Luminous verwenden . Es ist in Swift geschrieben. Sie müssen nur anrufen:

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

oder

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

1

Schnelle Implementierung des obigen Codes: -

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


}

Nennen Sie es aus einer anderen Klasse.

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

Beim Testen des zurückgegebenen Werts entspricht dies dem anderer Apps. Zumindest in meinem iPhone 6S +. Es ist nur die schnelle Implementierung der oben gezeigten Antwort. Und für mich hat die akzeptierte Antwort nicht funktioniert.


0

ChrisJF Antwort 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

}


0

Swift 5-Erweiterung für FileManagermit korrekter Fehlerbehandlung und ohne automatische Zeichenfolgenkonvertierung (konvertieren Sie die Byteanzahl nach Ihren Wünschen in Zeichenfolgen). Folgt auch FileManagerder Benennung.

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

Anwendungsbeispiel:

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)")
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.