Como detectar o espaço total em disco disponível / livre no dispositivo iPhone / iPad?

147

Estou procurando uma maneira melhor de detectar o espaço em disco disponível / livre no dispositivo iPhone / iPad programaticamente.
Atualmente, estou usando o NSFileManager para detectar o espaço em disco. A seguir está o trecho de código que faz o trabalho para mim:

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


Estou correto com o trecho acima? ou existe alguma maneira melhor de conhecer o espaço total em disco disponível / livre.
Tenho que detectar o total de espaço livre em disco, pois precisamos impedir que nosso aplicativo execute sincronização no cenário de pouco espaço em disco.

Code.Warrior
fonte
Espero que a ligação stackoverflow irá ajudá-lo ..
senthilMuthu
1
Parece que o código que ele está usando na pergunta é melhor que o código no link que você forneceu (ele está apenas verificando um diretório em vez de percorrer todos os subdiretórios em "/")
Kendall Helmstetter Gelner,
Obrigado Mikhail pelo link. Mas estou procurando espaço total em disco disponível / livre no dispositivo iPhone / iPad, não apenas uma pasta específica. Por exemplo, em um iPhone de 32 GB, se o tamanho total disponível / gratuito for de 28 GB, eu devo conseguir detectá-lo programaticamente.
precisa saber é o seguinte
Espero que este link ajude: jayprakashdubey.blogspot.in/2014/07/…
Jayprakash Dubey

Respostas:

152

ATUALIZAÇÃO : Como se passou muito tempo após esta resposta e novos métodos / APIs foram adicionados, verifique as respostas atualizadas abaixo para o Swift etc; Como eu não os usei, não posso atestá-los.

Resposta original : Encontrei a seguinte solução trabalhando para mim:

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

Ele me retorna exatamente o tamanho que o iTunes exibe quando o dispositivo está conectado à máquina.

Code.Warrior
fonte
4
A conversão em um flutuador pode gerar resultados imprecisos acima de 2 GB. Se você precisar lidar com tamanhos de arquivo muito grandes, use um duplo duplo ou longo.
Ash
Como apontado por Ash, esse método tem um resultado impreciso. No meu iPad 2, com 64 GB, falha em +0,25 GB ... O método abaixo, publicado por David H, tem o resultado exato ao usar os vars uint64_t.
Leandro Alves
3
O snippet de código foi editado para refletir sugestões de @David H, como mostrado abaixo.
Code.Warrior
4
+200 MB não é um problema. Nas configurações, tenho espaço disponível em "0 bytes". E quando entro e uso meu aplicativo, esse método relata cerca de 150mb de espaço livre. Então preencheu esse espaço restante e só então o aplicativo falha. Então, eu diria que esse método fornece informações mais corretas do que as exibidas em Configurações.
Ancajic
4
Por que ninguém está usando em NSUIntegervez de coisas como uint64_t? Estamos escrevendo Obj-C, não C ++ ou C. O NSUInteger fornecerá um número inteiro de 64 bits sem sinal agora, mas se as coisas mudarem, imagino que a Apple atualize essa macro (digamos que 128 bits em algum momento se torne real)
Goles 27/07
59

Origem revisada usando não assinado por muito tempo:

- (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: parece que alguém editou este código para usar 'uint64_t' em vez de 'unsigned long long'. Enquanto no futuro previsível, isso deve ser bom, eles não são os mesmos. 'uint64_t' é de 64 bits e sempre será isso. Em 10 anos, 'longo prazo' pode ser 128. é um pequeno ponto, mas por que eu usei unsignedLongLong.

David H
fonte
Não tenho experiência com o novo sistema de contagem automática, mas para que serve o __autoreleasing? Normalmente, você não precisa liberar automaticamente o NSError retornado
o Reverendo
Isto pode ajudar: stackoverflow.com/questions/8862023/...
Fabian Kreiser
3
no meu iPod Touch de 4ª geração com iOS 5.1, o NSFileSystemFreeSize ainda está relatando ~ 200 MBytes demais. Eu imprimo o conteúdo de todo o NSDictionary no depurador ... NSFileSystemSize está correto embora ... alguém tem solução para esse problema?
Zennichimaro 24/01
@Zennichimaro: Você resolveu o seu problema? Também estou enfrentando o mesmo problema, obtendo 0,2 GB extra ao verificar o espaço livre no iPad. O iPad está mostrando 24,1 GB de espaço disponível, mas no código está mostrando 24,3 GB.
Sudheer Kumar Palchuri
1
@Diejmon, você não pode solicitar ao NSNumber um tamanho inteiro desse tipo. É por isso que, para essas coisas, prefiro uma unidade de tamanho de bit conhecido. Embora tecnicamente eu concorde com a sua declaração, já tenho avisos suficientes para lidar com o uso do NSInteger e formatar seqüências de caracteres! 64 bits serão bits suficientes com certeza na minha vida e na sua.
David H
34

Eu escrevi uma classe para obter memória disponível / usada usando o Swift. Demonstração em: https://github.com/thanhcuong1990/swift-disk-status
Swift 4 atualizado.

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

obtenha o status do espaço em disco com o Swift

Cuong Lam
fonte
Você tem alguma idéia de por que o MBFormatter está lá? Não é usado em nenhum lugar.
Ben Sinclair
MBFormatter é uma função para converter qualquer valor em MB. Eu não estou usando para projeto de demonstração. Mas eu preciso de outro projeto.
Cuong Lam
1
É ótimo colocar uma extensão do FileManager.
Leon
2
O iTunes mostra 18,99 GB de graça, mas recebo 13,41 GB quando uso os métodos descritos. Alguém sabe o que eu sinto falta?
Vitalii Boiarskyi
1
@CuongLam Os erros de desempacotamento não são lançados e não são pegos pelo do / catch. O código-fonte de amostra deve ser gravado para manipular os erros corretamente. stackoverflow.com/questions/34628999/…
SafeFastExpressive
26

Se você precisar de uma sequência de caracteres formatada com tamanho, consulte a boa biblioteca no 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
fonte
2
Para o formato, pode-se também usar NSBytCounterFormatter
Daniel Barden
Este ainda é propenso a mesma bug + 200MB: stackoverflow.com/questions/9270027/...
Paulius Liekis
13

Não use 'não assinado', são apenas 32 bits que ultrapassarão os 4 GB, menos do que o espaço livre típico do iPad / iPhone. Use não assinado por muito tempo (ou uint64_t) e recupere o valor do NSNumber como um int de 64 bits também usando unsignedLongLongValue.

Christopher Lloyd
fonte
3
É melhor do que uma dica - "It's the Law" :-) Como ele disse, o código original está completamente errado.
7264 David H
13

Se você deseja obter o espaço livre restante usando o Swift, é um pouco diferente. Você precisa usar attributeOfFileSystemForPath () em vez de attributeOfItemAtPath ():

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: Atualizado para Swift 1.0
Edit 2: Atualizado para a segurança, usando a resposta de Martin R .
Edit 3: Updated for Swift 2.0 (por dgellow )

RubenSandwich
fonte
Eu estava tentando usar essa resposta, mas ela não será compilada no GM ([NSObject: AnyObject]? Não possui um membro chamado 'subscrito'). Acho que isso se deve à questão levantada aqui, mas não entendo como fazer essa resposta funcionar nesse contexto. Qualquer ajuda muito apreciada.
Bryan Hanson
Atualizei a resposta para trabalhar no Swift 1.0 agora. Porque attributeOfFileSystemForPath retorna [NSObject: AnyObject]? você precisa transmitir para o NSDictionary? como poderia ser nulo e, em seguida, desembrulhe o dicionário para subscrevê-lo. (Isso é um pouco inseguro, então eu vou atualizar a resposta um pouco este último com uma solução mais segura quando eu tenho o tempo.)
RubenSandwich
Obrigado pela atualização. Acontece que, cerca de uma hora antes da sua resposta, eu fui adiante e formulei a questão como uma nova pergunta aqui . Há uma resposta lá agora, mas como esse método de lidar com os opcionais é um pouco opaco para mim, eu adoraria ver outra abordagem para sua conveniência. Cumprimente sua irmã Rachel.
Bryan Hanson
Bryan, sugiro a primeira resposta à sua pergunta respondida, pois é uma boa mistura de segurança e clareza. Não tenho certeza se poderia dar uma resposta melhor que essa. Os opcionais podem ser confusos no começo, eu sugiro que leia a seção de manuais Swift sobre os opcionais .
precisa saber é o seguinte
Muito apreciado, examinarei esse manual novamente e também encontrei algumas boas perguntas para SO. Bryan
Bryan Hanson
9

Aqui está a minha resposta e por que é melhor.

Resposta (rápida):

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
}

Resposta (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 que é melhor:

  • Utiliza a biblioteca incorporada do Cocoa NSByteCountFormatter, o que significa que não há cálculos manuais malucos, de bytes a gigabytes. A Apple faz isso por você!
  • Facilmente traduzível: NSByteCountFormatterfaz isso por você. Por exemplo, quando o idioma do dispositivo estiver definido como inglês, a string lerá 248,8 MB, mas lerá 248,8 Mo quando definida como francês, etc. para outros idiomas.
  • Um valor padrão é fornecido em caso de erro.
ChrisJF
fonte
1
@JuanBoero Postado em Swift 3.1 (finalmente)!
ChrisJF
7

Esclarecimentos importantes (pelo menos para mim). Se eu conectar meu iPod ao meu Mac, essas são as informações exibidas pelo iTunes App.

Informações de memória do iPod do aplicativo iTunes

Quando eu uso o código acima:

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

O countStyle NSByteCountFormatterCountStyleFile mostra-me: 17,41 GB

O countStyle NSByteCountFormatterCountStyleBinary me mostra: 16,22 GB

16,22 GB ( NSByteCountFormatterCountStyleBinary ) É EXATAMENTE o número que o iTunes App me mostra quando conecto meu iPod ao Mac.

Markus
fonte
talvez o arquivo seja apenas para arquivos MAC e não para iOS?
João Nunes
que é a mesma quantidade de byte multiplicado como 1000 (KB, em seguida, MB, em seguida, GB) versus 1024.
Jim75
7

Atualize com uma nova API precisa para obter o tamanho disponível no disco disponível no iOS11. Aqui está a descrição para a nova chave de recurso da 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

Cruzei os resultados da chave " FileAttributeKey.systemFreeSize " e da chave " URLResourceKey.volumeAvailableCapacityForImportantUsageKey " e encontrei os resultados retornados no formulário " volumeAvailableCapacityForImportantUsageKey " exatamente corresponde ao armazenamento disponível mostrado na interface do usuário. Comparação de espaço livre em disco disponível Aqui está a rápida implementação:

class var freeDiskSpaceInBytesImportant:Int64 {
    get {
        do {
            return try URL(fileURLWithPath: NSHomeDirectory() as String).resourceValues(forKeys: [URLResourceKey.volumeAvailableCapacityForImportantUsageKey]).volumeAvailableCapacityForImportantUsage!
        } catch {
            return 0
        }
    }
}
Evilisn Jiang
fonte
De onde vem o "uso oportunista" na sua captura de tela?
rshev
Encontrei volumeAvailableCapacityForOpportunisticUsageKey.
rshev
Sim rshev, volumeAvailableCapacityForOpportunisticUsageKey obtém "uso oportunista" na minha captura de tela
Evilisn Jiang 15/17
para ver o tamanho de armazenamento disponível, devo consultar com NSHomeDirectory()ou NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true). Existe alguma diferença usando esses dois?
Suryakant Sharma
7

Você pode encontrar outra solução usando o Swift 4 e extensionoferecendo uma boa opção.

Aqui está a UIDeviceextensão.

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 uso da amostra:

UIDevice.current.totalDiskSpaceInBytes()
UIDevice.current.totalDiskSpace()
UIDevice.current.freeDiskSpaceInBytes()
UIDevice.current.freeDiskSpace()
UIDevice.current.usedDiskSpaceInBytes()
UIDevice.current.usedDiskSpace()
abdullahselek
fonte
Não use, em !vez disso, coloque um guardno cofre typecastingou nilverifique.
precisa saber é o seguinte
Obrigado por seus comentários @TheTiger.
Abdullahselek #
3

Para iOS> = 6.0, você pode usar o novo NSByteCountFormatter. Esse código obtém o número de bytes livres restantes como uma seqüência de caracteres formatada.

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
fonte
2

O código a seguir é a implementação da versão Swift 3.0 da resposta fornecida anteriormente 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
fonte
Por que isso está retornando mais do que as informações de espaço em disco disponíveis do iPhone. Quando o menu de configuração dos iPhones diz 998MB, isso retorna 1,2 GB
Espero que seja
1

para Swift como extensão 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
        }
    }
}

Como usar:

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

A saída será:

Memory 9656 of 207694 Mb available.
ale_stro
fonte
1

Sei que este post é um pouco antigo, mas acho que essa resposta pode ajudar alguém. Se você quiser conhecer o espaço em disco usado / livre / total no dispositivo, use o Luminous . Está escrito em Swift. Você só precisa ligar para:

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

ou

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

Implementação rápida do código acima: -

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


}

Ligue de qualquer outra 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");
    }

Ao testar o valor retornado, é o mesmo mostrado por outros aplicativos. Pelo menos no meu iPhone 6S +. É apenas a rápida implementação da resposta mostrada acima. E para mim a resposta aceita não funcionou.

Bikram
fonte
0

Resposta do ChrisJF na versão 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

}
Juan Boero
fonte
0

Extensão Swift 5 para FileManagertratamento de erros adequado e sem conversões automáticas de string (converta a contagem de bytes em string conforme sua preferência). Também segue FileManagera nomeação.

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

Exemplo 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)")
}
ivanzoid
fonte