¿Cómo detectar el espacio total disponible / libre en el dispositivo iPhone / iPad?

147

Estoy buscando una mejor manera de detectar el espacio en disco disponible / libre en el dispositivo iPhone / iPad mediante programación.
Actualmente estoy usando NSFileManager para detectar el espacio en disco. El siguiente es el fragmento del código que hace el trabajo por mí:

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


¿Estoy correcto con el fragmento anterior? ¿O hay alguna forma mejor de saber el espacio total disponible / libre en el disco?
Tengo que detectar el espacio libre total en disco, ya que debemos evitar que nuestra aplicación realice la sincronización en el escenario de poco espacio en disco.

Code.Warrior
fuente
Espero que el enlace stackoverflow le ayudará a ..
senthilMuthu
1
Parece que el código que está usando en su pregunta es mejor que el código en el enlace que ha proporcionado (solo está revisando un directorio en lugar de recorrer todos los subdirectorios en "/")
Kendall Helmstetter Gelner
Gracias Mikhail por el enlace. Pero estoy buscando el espacio total disponible / libre en el disco del dispositivo iPhone / iPad, no solo una carpeta en particular. Por ejemplo, en un iPhone de 32 GB, si el tamaño total disponible / libre es de 28 GB, debería poder detectarlo mediante programación.
Code.Warrior
Espero que este enlace ayude: jayprakashdubey.blogspot.in/2014/07/…
Jayprakash Dubey

Respuestas:

152

ACTUALIZACIÓN : Dado que ha pasado mucho tiempo después de esta respuesta y se han agregado nuevos métodos / API, verifique las respuestas actualizadas a continuación para Swift, etc. Como no los he usado yo mismo, no puedo responder por ellos.

Respuesta original : Encontré la siguiente solución funcionando para mí:

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

Me devuelve exactamente el tamaño que muestra iTunes cuando el dispositivo está conectado a la máquina.

Code.Warrior
fuente
44
La conversión a un flotante puede dar resultados inexactos por encima de alrededor de 2 GB. Si necesita lidiar con tamaños de archivo realmente grandes, use un doble doble o largo en su lugar.
Ash
Como señaló Ash, este método tiene un resultado inexacto. En mi iPad 2, con 64 GB, falla en +0.25 GB ... El método a continuación, publicado por David H, tiene el resultado exacto al usar uint64_t vars.
Leandro Alves
3
El fragmento de código se ha editado para reflejar las sugerencias de @David H como se muestra a continuación.
Code.Warrior
44
+200 MB no es un problema. En la configuración tengo espacio disponible de "0 bytes". Y cuando entro y uso mi aplicación, este método informa sobre 150mb de espacio libre. Luego lleno este espacio restante y solo entonces la aplicación se bloquea. Entonces, diría que este método le brinda más información correcta que la que ve en Configuración.
ancajic
44
¿Por qué nadie usa en NSUIntegerlugar de cosas como uint64_t? Estamos escribiendo Obj-C, no C ++ o C. NSUInteger le dará un entero de 64 bits sin signo ahora, pero si las cosas cambian, imagino que Apple actualizará esa Macro (digamos 128 bits en algún momento, se vuelve real)
Goles
59

Fuente revisada usando 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;
}

EDITAR: parece que alguien editó este código para usar 'uint64_t' en lugar de 'unsigned long long'. Si bien en el futuro previsible esto debería estar bien, no son lo mismo. 'uint64_t' es de 64 bits y siempre será eso. En 10 años, 'unsigned long long' podría ser 128. es un pequeño punto, pero por qué usé unsignedLongLong.

David H
fuente
No tengo experiencia con el nuevo sistema de conteo automático, pero ¿para qué es el __autoreleasing? Normalmente no es necesario liberar automáticamente el NSError devuelto
el reverendo
Esto podría ayudar: stackoverflow.com/questions/8862023/…
Fabian Kreiser
3
en mi iPod Touch 4th Gen con iOS 5.1, NSFileSystemFreeSize sigue reportando ~ 200 MBytes demasiado. Imprimo el contenido de todo el NSDictionary en el depurador ... NSFileSystemSize es correcto ... ¿Alguien tiene solución para este problema?
Zennichimaro
@Zennichimaro: ¿Arreglaste tu problema? También estoy enfrentando el mismo problema, obteniendo 0.2 GB adicionales cuando reviso el espacio libre en el iPad. El iPad muestra 24.1 GB de espacio disponible, pero en el código muestra 24.3 GB.
repente Kumar Palchuri
1
@Diejmon no puedes pedirle a NSNumber un tamaño integeral de este tipo. Es por eso que para tales cosas prefiero una unidad de tamaño de bit conocido. Aunque técnicamente estoy de acuerdo con su declaración, ¡ya tengo suficientes advertencias para manejar el uso de NSInteger y las cadenas de formato! 64 bits serán suficientes para mi vida y la tuya.
David H
34

He escrito una clase para obtener memoria disponible / usada usando Swift. Demostración en: https://github.com/thanhcuong1990/swift-disk-status
Swift 4 actualizado.

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

}

Manifestación

obtener el estado del espacio en disco con Swift

Cuong Lam
fuente
¿Tienes alguna idea de por qué MBFormatter está ahí? No se usa en ningún lado.
Ben Sinclair
MBFormatter es una función para convertir cualquier valor en valor MB. No lo estoy usando para proyecto de demostración. Pero necesito otro proyecto.
Cuong Lam
1
Esto es genial para poner en una extensión FileManager.
Leon
2
iTunes muestra 18.99 GB gratis pero obtengo 13.41 GB cuando uso los métodos descritos. ¿Alguien sabe lo que extraño?
Vitalii Boiarskyi
1
@CuongLam Los errores de desenvolvimiento no se lanzan y no son capturados por do / catch. El código fuente de muestra debe escribirse para manejar los errores correctamente. stackoverflow.com/questions/34628999/…
SafeFastExpressive
26

Si necesita una cadena formateada con tamaño, puede echar un vistazo a la buena biblioteca en 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;
}
0x8BADF00D
fuente
2
Para formatear, también se puede usar NSBytCounterFormatter
Daniel Barden
Esto todavía es propenso al mismo error de + 200MB: stackoverflow.com/questions/9270027/…
Paulius Liekis
13

No use 'sin firmar', solo son 32 bits que se desbordarán más de 4 GB, que es menos que el espacio libre típico de iPad / iPhone. Use unsigned long long (o uint64_t) y recupere el valor del NSNumber como un int de 64 bits también usando unsignedLongLongValue.

Christopher Lloyd
fuente
3
Es mejor que un consejo: "Es la ley" :-) Como dijo, el código original es simplemente incorrecto.
David H
13

Si está buscando obtener el espacio libre restante usando Swift, es ligeramente diferente. Necesita usar los atributos deFileSystemForPath () en lugar de los atributosOfItemAtPath ():

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

Editar: Actualización de Swift 1.0
Edición 2: Actualización de seguridad, utilizando la respuesta de Martin R .
Edición 3: actualizado para Swift 2.0 (por dgellow )

RubenSandwich
fuente
Estaba tratando de usar esta respuesta, pero no se compilará bajo GM ([NSObject: AnyObject]? No tiene un miembro llamado 'subíndice'). Creo que esto se debe al problema planteado aquí, pero no entiendo cómo hacer que esa respuesta funcione en este contexto. Cualquier ayuda muy apreciada.
Bryan Hanson el
Actualicé la respuesta para trabajar en Swift 1.0 ahora. ¿Porque atributosOfFileSystemForPath devuelve [NSObject: AnyObject]? necesitas lanzar a NSDictionary? ya que podría ser nulo y luego desenvolver el diccionario para subscribirlo. (Eso es un poco inseguro, así que actualizaré la respuesta un poco más
tarde
Gracias por la actualización. Resulta que, aproximadamente una hora antes de su respuesta, seguí adelante y formulé el problema como una nueva pregunta aquí . Ahora hay una respuesta allí, pero dado que este método de tratar con opcionales es un poco opaco para mí, me encantaría ver otro enfoque a su conveniencia. Saluda a tu hermana Rachel.
Bryan Hanson
Bryan, sugeriría la primera respuesta a tu pregunta, ya que es una buena combinación de seguridad y claridad. No estoy seguro de poder dar una mejor respuesta que esa. Los opcionales pueden ser confusos al principio, sugiero leer la sección de manuales de Swift sobre opcionales , es bastante bueno.
RubenSandwich
Muy apreciado, volveré a mirar ese manual y también he encontrado algunas buenas preguntas SO. Bryan
Bryan Hanson
9

Aquí está mi respuesta y por qué es mejor.

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

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

Por qué es mejor:

  • Utiliza la biblioteca integrada de Cocoa NSByteCountFormatter, lo que significa que no hay cálculos manuales locos de bytes a gigabytes. ¡Apple hace esto por ti!
  • Fácilmente traducible: NSByteCountFormatterhace esto por usted. Por ejemplo, cuando el idioma del dispositivo está configurado en inglés, la cadena leerá 248.8 MB pero leerá 248,8 Mo cuando esté configurado en francés, etc. para otros idiomas.
  • Se da un valor predeterminado en caso de error.
ChrisJF
fuente
1
@JuanBoero ¡Publicado en Swift 3.1 (finalmente)!
ChrisJF
7

Aclaración importante (al menos para mí). Si conecto mi iPod a mi Mac, esta es la información que muestra la aplicación iTunes.

Información de la memoria del iPod de la aplicación iTunes

Cuando uso el código anterior:

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 muéstrame: 17,41 GB

CountStyle NSByteCountFormatterCountStyleBinary muéstrame: 16,22 GB

16,22 GB ( NSByteCountFormatterCountStyleBinary ) Es EXACTAMENTE el número que la aplicación iTunes me muestra cuando conecto mi iPod a mi Mac.

Markus
fuente
¿Tal vez el archivo es solo para archivos MAC y no para iOS?
João Nunes
es la misma cantidad de bytes multiplicado por 1000 (KB, MB y GB) versus 1024.
Jim75
7

Actualice con una nueva API precisa para obtener el tamaño disponible en el disco disponible en iOS11. Aquí está la descripción de la nueva clave de recurso 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

Comparé los resultados de la clave " FileAttributeKey.systemFreeSize " y la clave " URLResourceKey.volumeAvailableCapacityForImportantUsageKey " y encontré que los resultados devueltos del formulario " volumeAvailableCapacityForImportantUsageKey " coinciden exactamente con el almacenamiento disponible que se muestra en la interfaz de usuario. Comparación de espacio libre en disco disponible Aquí está la implementación rápida:

class var freeDiskSpaceInBytesImportant:Int64 {
    get {
        do {
            return try URL(fileURLWithPath: NSHomeDirectory() as String).resourceValues(forKeys: [URLResourceKey.volumeAvailableCapacityForImportantUsageKey]).volumeAvailableCapacityForImportantUsage!
        } catch {
            return 0
        }
    }
}
Evilisn Jiang
fuente
¿De dónde viene el "uso oportunista" en tu captura de pantalla?
rshev
Encontrado, volumeAvailableCapacityForOpportunisticUsageKey.
rshev
Sí rshev, volumeAvailableCapacityForOpportunisticUsageKey obtiene "" uso oportunista "en mi captura de pantalla
Evilisn Jiang
para ver el tamaño de almacenamiento disponible debo consultar con NSHomeDirectory() o NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true). ¿Hay alguna diferencia usando estos dos?
Suryakant Sharma
7

Puedes encontrar otra solución usando Swift 4 y extensionque te da una buena opción.

Aquí está la UIDeviceextensión.

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

}

Y uso de la muestra:

UIDevice.current.totalDiskSpaceInBytes()
UIDevice.current.totalDiskSpace()
UIDevice.current.freeDiskSpaceInBytes()
UIDevice.current.freeDiskSpace()
UIDevice.current.usedDiskSpaceInBytes()
UIDevice.current.usedDiskSpace()
abdullahselek
fuente
No utilice !en su lugar poner un guardseguro typecastingo nilcomprobar.
TheTiger
Gracias por tus comentarios @TheTiger.
abdullahselek
3

Para iOS> = 6.0 puede usar el nuevo NSByteCountFormatter. Este código obtiene el número de bytes libres restantes como una cadena formateada.

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];
Robert
fuente
2

El siguiente código es la implementación de la versión Swift 3.0 de la respuesta proporcionada previamente por 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

}
ggruen
fuente
¿Por qué eso devuelve más información del espacio disponible en el disco del iPhone? Cuando el menú de configuración de iPhones dice 998MB, eso devuelve 1.2 GB
Hope
1

para Swift como extensión 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
        }
    }
}

Cómo utilizar:

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

La salida será:

Memory 9656 of 207694 Mb available.
ale_stro
fuente
1

Sé que esta publicación es un poco antigua, pero creo que esta respuesta puede ayudar a alguien. Si desea conocer el espacio de disco usado / libre / total en el dispositivo, puede usar Luminous . Está escrito en Swift. Solo tienes que llamar a:

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

o

Luminous.System.Disk.freeSpaceInBytes()
Luminous.System.Disk.usedSpaceInBytes()
Andrea Mario Lufino
fuente
1

Implementación rápida del código anterior: -

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


}

Llámalo desde cualquier otra clase.

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

Al probar el valor devuelto, es el mismo que muestran otras aplicaciones. Al menos en mi iPhone 6S +. Es solo la rápida implementación de la respuesta mostrada anteriormente. Y para mí la respuesta aceptada no funcionó.

Bikram
fuente
0

Respuesta de ChrisJF en la versión 2.1 de Swift :

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

}
Juan boero
fuente
0

Extensión Swift 5 para FileManagerel manejo adecuado de errores y sin conversiones automáticas de cadenas (convierta el recuento de bytes a cadenas como prefiera). También sigue FileManagerlos nombres.

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

Ejemplo de uso:

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