Come rilevare lo spazio su disco disponibile / libero totale sul dispositivo iPhone / iPad?


147

Sto cercando un modo migliore per rilevare lo spazio disponibile / libero su disco sul dispositivo iPhone / iPad a livello di codice.
Attualmente sto usando NSFileManager per rilevare lo spazio su disco. Di seguito è riportato lo snippet del codice che fa il lavoro per 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;
}


Sono corretto con il frammento sopra? o esiste un modo migliore per conoscere lo spazio totale disponibile / libero su disco.
Devo rilevare lo spazio libero su disco totale, poiché dobbiamo impedire alla nostra applicazione di eseguire la sincronizzazione nello scenario di spazio su disco ridotto.


Spero che il link StackOverflow ti aiuti ..
senthilMuthu,

1
Sembra che il codice che sta usando nella sua domanda sia migliore del codice nel link che hai dato (sta solo controllando una directory invece di attraversare tutte le sottodirectory in "/")
Kendall Helmstetter Gelner

Grazie Mikhail per il link. Ma sto cercando lo spazio su disco disponibile / libero totale sul dispositivo iPhone / iPad, non solo una cartella particolare. Ad esempio, su un iPhone da 32 GB, se la dimensione disponibile / libera totale è di 28 GB, dovrei essere in grado di rilevarlo a livello di codice.
Guerriero

Spero che questo link sia di aiuto: jayprakashdubey.blogspot.in/2014/07/…
Jayprakash Dubey

Risposte:


152

AGGIORNAMENTO : poiché è trascorso molto tempo dopo che questa risposta e nuovi metodi / API sono stati aggiunti, si prega di controllare le risposte aggiornate di seguito per Swift ecc; Dal momento che non li ho usati io stesso, non posso garantire per loro.

Risposta originale : ho trovato la seguente soluzione funzionante per 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;
}

Mi restituisce esattamente le dimensioni visualizzate da iTunes quando il dispositivo è collegato alla macchina.


4
La conversione in float può dare risultati imprecisi superiori a circa 2 GB. Se devi gestire file di dimensioni molto grandi, usa invece un doppio o un doppio lungo.
Ash

Come indicato da Ash, questo metodo ha un risultato impreciso. Nel mio iPad 2, con 64 GB, non riesce di +0,25 GB ... Il metodo seguente, pubblicato da David H, ha il risultato esatto quando si usa uint64_t vars.
Leandro Alves,

3
Lo snippet di codice è stato modificato per riflettere i suggerimenti di @David H come mostrato di seguito.
Code.Warrior

4
+200 MB non è un problema. Nelle impostazioni ho "0 byte" di spazio disponibile. E quando entro e utilizzo la mia app, questo metodo riporta circa 150 MB di spazio libero. Quindi riempio questo spazio rimanente e solo allora l'app si arresta in modo anomalo. Quindi direi che questo metodo ti dà informazioni più corrette di quelle che vedi in Impostazioni.
ancajic,

4
Perché nessuno usa al NSUIntegerposto di cose come uint64_t? Stiamo scrivendo Obj-C, non C ++ o C. NSUInteger ti fornirà un numero intero a 64 bit senza segno ora, ma se le cose cambiano immagino che Apple aggiornerà quella Macro (diciamo 128 bit a un certo punto, diventa reale)
Goles,

59

Sorgente rivista utilizzando 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: sembra che qualcuno abbia modificato questo codice per usare 'uint64_t' invece di 'unsigned long long'. Mentre nel prossimo futuro questo dovrebbe andare bene, non sono gli stessi. 'uint64_t' è 64 bit e sarà sempre quello. In 10 anni "unsigned long long" potrebbe essere 128. è un piccolo punto, ma perché ho usato unsignedLongLong.


Non ho esperienza con il nuovo sistema di conteggio automatico ma a cosa serve __autoreleasing? Normalmente non è necessario rilasciare automaticamente l'NSError restituito
il reverendo


3
sul mio iPod Touch di quarta generazione con iOS 5.1, NSFileSystemFreeSize riporta ancora ~ 200 MByte in eccesso. Stampo il contenuto dell'intero NSDictionary nel debugger ... NSFileSystemSize è corretto però ... qualcuno ha una soluzione per questo problema?
Zennichimaro,

@Zennichimaro: hai risolto il tuo problema? Inoltre sto affrontando lo stesso problema, ricevendo 0,2 GB in più quando controllo lo spazio libero su iPad. iPad mostra 24.1 GB di spazio disponibile ma nel codice mostra 24.3 GB.
Sudheer Kumar Palchuri,

1
@Diejmon non puoi chiedere a NSNumber una dimensione intera di questo tipo. Questo è il motivo per cui per queste cose preferisco un'unità di dimensioni di bit note. Mentre tecnicamente sono d'accordo con la tua affermazione, ho già abbastanza avvertenze per gestire NSInteger e formattare le stringhe! 64 bit saranno sicuramente abbastanza bit nella mia vita e nella tua.
David H

34

Ho scritto un corso per ottenere memoria disponibile / usata usando Swift. Demo su: https://github.com/thanhcuong1990/swift-disk-status
Swift 4 aggiornato.

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

}

dimostrazione

ottenere lo stato dello spazio su disco con Swift


Hai idea del perché c'è MBFormatter? Non è usato da nessuna parte.
Ben Sinclair,

MBFormatter è una funzione per convertire qualsiasi valore in valore MB. Non lo sto usando per un progetto demo. Ma ho bisogno di altri progetti.
Cuong Lam,

1
È fantastico inserire un'estensione FileManager.
Leon,

2
iTunes mostra 18,99 GB gratuiti ma ottengo 13,41 GB quando utilizzo i metodi descritti. Qualcuno sa cosa mi manca?
Vitalii Boiarskyi,

1
@CuongLam Gli errori di Unwrapping non vengono generati e non vengono rilevati da do / catch. Il codice sorgente di esempio deve essere scritto per gestire correttamente gli errori. stackoverflow.com/questions/34628999/...
SafeFastExpressive

26

Se hai bisogno di stringhe formattate con dimensioni puoi dare un'occhiata alla bella libreria su 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
Per formattare, si può anche usare NSBytCounterFormatter
Daniel Barden

Questo è ancora incline a stesso bug + 200MB: stackoverflow.com/questions/9270027/...
Paulius Liekis

13

Non usare "unsigned", sono solo 32 bit che supereranno i 4 GB, che è inferiore al tipico spazio libero su iPad / iPhone. Usa unsigned long long (o uint64_t) e recupera il valore da NSNumber come int a 64 bit usando unsignedLongLongValue.


3
È meglio di un suggerimento: "È la legge" :-) Come ha detto, il codice originale è semplicemente sbagliato.
David H,

13

Se stai cercando di ottenere lo spazio libero rimanente con Swift, è leggermente diverso. Devi usare attributiOfFileSystemForPath () invece di attributiOfItemAtPath ():

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

Modifica: Aggiornato per Swift 1.0
Edit 2: Aggiornamento per la sicurezza, con la risposta di Martin R .
Modifica 3: aggiornato per Swift 2.0 (di dgellow )


Stavo cercando di usare questa risposta, ma non verrà compilata sotto GM ([NSObject: AnyObject]? Non ha un membro chiamato 'subscript'). Penso che questo sia dovuto al problema sollevato qui, ma non capisco come far funzionare quella risposta in questo contesto. Qualsiasi aiuto è molto apprezzato.
Bryan Hanson,

Ho aggiornato la risposta per lavorare su Swift 1.0 ora. Perché attributiOfFileSystemForPath restituisce [NSObject: AnyObject]? devi trasmettere a NSDictionary? poiché potrebbe essere nullo e quindi scartare il dizionario per sottoscriverlo. (È un po 'pericoloso, quindi aggiornerò la risposta un po' più
tardi

Grazie per l'aggiornamento. A quanto pare, circa un'ora prima della tua risposta ero andato avanti e ho formulato il problema come una nuova domanda qui . C'è una risposta lì ora, ma poiché questo metodo di gestione degli optionals è un po 'opaco per me, mi piacerebbe vedere un altro approccio a vostro piacimento. Saluti tua sorella Rachel.
Bryan Hanson,

Bryan, suggerirei la prima risposta alla tua domanda di risposta in quanto è un buon mix di sicurezza e chiarezza. Non sono sicuro di poter dare una risposta migliore di quella. Gli opzionali possono essere fonte di confusione all'inizio, consiglio vivamente di leggere la sezione dei manuali Swift sugli opzionali , è abbastanza buono.
RubenSandwich,

Molto apprezzato, guarderò di nuovo quel manuale e ho trovato anche alcune buone domande SO. Bryan
Bryan Hanson,

9

Ecco la mia risposta e perché è meglio.

Risposta (rapida):

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
}

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

Perché è meglio:

  • Utilizza la libreria integrata di Cocoa NSByteCountFormatter , il che significa che non ci sono calcoli manuali pazzi da byte a gigabyte. Apple fa questo per te!
  • Facilmente traducibile: lo NSByteCountFormatterfa per te. Ad esempio, quando la lingua del dispositivo è impostata su inglese, la stringa leggerà 248,8 MB ma leggerà 248,8 Mo se impostato su francese, ecc. Per altre lingue.
  • Viene fornito un valore predefinito in caso di errore.

1
@JuanBoero, pubblicato in Swift 3.1 (finalmente)!
ChrisJF,

7

Chiarimento importante (almeno per me). Se collego il mio iPod al mio Mac, queste sono le informazioni mostrate dall'app iTunes.

Informazioni sulla memoria dell'iPod dall'app iTunes

Quando uso il codice sopra:

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 mostrami: 17,41 GB

The countStyle NSByteCountFormatterCountStyleBinary mi mostra: 16,22 GB

16,22 GB ( NSByteCountFormatterCountStyleBinary ) È ESATTAMENTE il numero che l'app iTunes mi mostra quando collego il mio iPod al mio Mac.


forse File è solo per file MAC e non iOS?
João Nunes,

è la stessa quantità di byte moltiplicata per 1000 (KB quindi MB quindi GB) rispetto a 1024.
Jim75

7

Aggiorna con una nuova API accurata per ottenere le dimensioni disponibili sul disco disponibili in iOS11. Ecco la descrizione per la nuova chiave di risorsa 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

Ho incrociato i risultati dalla chiave " FileAttributeKey.systemFreeSize " e dalla chiave " URLResourceKey.volumeAvailableCapacityForImportantUsageKey " e ho trovato i risultati restituiti da " volumeAvailableCapacityForImportantUsageKey " corrisponde esattamente alla memoria disponibile mostrata nell'interfaccia utente. Confronto dello spazio libero su disco disponibile Ecco l'implementazione rapida:

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

Da dove viene "l'utilizzo opportunistico" sul tuo screenshot?
rshev,

Trovato, volumeAvailableCapacityForOpportunisticUsageKey.
rshev,

Sì rshev, volumeDisponibilitàCapacitàForOpportunisticoUsageKey ottiene "" utilizzo opportunistico "sul mio screenshot
Evilisn Jiang,

per visualizzare le dimensioni di archiviazione disponibili dovrei eseguire una query con NSHomeDirectory()o NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true). C'è qualche differenza nell'usare questi due?
Suryakant Sharma,

7

Puoi trovare un'altra soluzione usando Swift 4 e extensionche ti dà una buona opzione.

Ecco l' UIDeviceestensione.

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

}

E utilizzo del campione:

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

Non utilizzare !invece mettere guarda sicuro typecastingo nilcontrollare.
TheTiger

Grazie per i tuoi commenti @TheTiger.
abdullahselek,

3

Per iOS> = 6.0 puoi usare il nuovo NSByteCountFormatter. Questo codice ottiene il numero di byte liberi rimanenti come stringa formattata.

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

Il codice seguente è l'implementazione della versione Swift 3.0 della risposta precedentemente fornita da 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

}

Perché questo restituisce più informazioni sullo spazio disponibile su disco dell'iPhone. Quando il menu di configurazione di iPhone dice 998 MB, questo restituisce 1,2 GB
Spero

1

per Swift come estensione 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
        }
    }
}

Come usare:

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

L'output sarà:

Memory 9656 of 207694 Mb available.

1

So che questo post è un po 'vecchio, ma penso che questa risposta possa aiutare qualcuno. Se si desidera conoscere lo spazio su disco utilizzato / libero / totale sul dispositivo, è possibile utilizzare Luminous . È scritto in Swift. Devi solo chiamare:

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

o

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

1

Rapida implementazione del codice precedente: -

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


}

Chiamalo da qualsiasi altra classe.

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

Durante il test del valore restituito, è lo stesso mostrato da altre app. Almeno nel mio iPhone 6S +. È solo l'implementazione rapida della risposta sopra indicata. E per me la risposta accettata non ha funzionato.


0

Risposta di ChrisJF nella versione Swift 2.1 :

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

Estensione Swift 5 per una FileManagercorretta gestione degli errori e nessuna conversione automatica delle stringhe (converti il ​​conteggio dei byte in stringa come preferisci). Segue anche FileManagerla denominazione.

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

Esempio di utilizzo:

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)")
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.