Comment détecter l'espace disque total disponible / libre sur l'appareil iPhone / iPad?

147

Je recherche un meilleur moyen de détecter par programmation l'espace disque disponible / libre sur l'appareil iPhone / iPad.
Actuellement, j'utilise NSFileManager pour détecter l'espace disque. Voici l'extrait de code qui fait le travail pour moi:

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


Ai-je raison avec l'extrait ci-dessus? ou y a-t-il un meilleur moyen de connaître l'espace disque total disponible / libre.
Je dois détecter l'espace disque libre total, car nous devons empêcher notre application d'effectuer la synchronisation dans le scénario d'espace disque faible.

Code.Warrior
la source
J'espère que le lien stackoverflow vous aidera ..
senthilMuthu
1
Il semble que le code qu'il utilise dans sa question soit meilleur que le code du lien que vous avez donné (il ne fait que vérifier un répertoire au lieu de parcourir tous les sous-répertoires sous "/")
Kendall Helmstetter Gelner
Merci Mikhail pour le lien. Mais je recherche l'espace disque total disponible / libre sur un appareil iPhone / iPad, pas seulement un dossier particulier. Par exemple, sur un iPhone de 32 Go, si la taille totale disponible / libre est de 28 Go, je devrais être en mesure de le détecter par programme.
Code.Warrior
J'espère que ce lien vous aidera: jayprakashdubey.blogspot.in/2014/07/…
Jayprakash Dubey

Réponses:

152

MISE À JOUR : Étant donné que beaucoup de temps s'est écoulé après cette réponse et que de nouvelles méthodes / API ont été ajoutées, veuillez vérifier les réponses mises à jour ci-dessous pour Swift, etc. Puisque je ne les ai pas utilisées moi-même, je ne peux pas en garantir.

Réponse originale : j'ai trouvé la solution suivante fonctionnant pour moi:

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

Cela me renvoie exactement la taille qu'iTunes affiche lorsque l'appareil est connecté à la machine.

Code.Warrior
la source
4
La conversion en flottant peut donner des résultats inexacts au-dessus d'environ 2 Go. Si vous devez gérer des fichiers de très grande taille, utilisez plutôt un double ou un long double.
Ash
Comme l'a souligné Ash, cette méthode a un résultat inexact. Dans mon iPad 2, avec 64 Go, il échoue de +0,25 Go ... La méthode ci-dessous, postée par David H, a le résultat précis lors de l'utilisation de vars uint64_t.
Leandro Alves
3
L'extrait de code a été modifié pour refléter les suggestions de @David H, comme indiqué ci-dessous.
Code.Warrior
4
+200 Mo n'est pas un problème. Dans les paramètres, j'ai "0 octets" d'espace disponible. Et lorsque j'entre et utilise mon application, cette méthode rapporte environ 150 Mo d'espace libre. Ensuite, je remplis cet espace restant et alors seulement l'application se bloque. Je dirais donc que cette méthode vous donne des informations plus correctes que ce que vous voyez dans les paramètres.
ancajic
4
Pourquoi personne n'utilise à la NSUIntegerplace de trucs comme uint64_t? Nous écrivons Obj-C, pas C ++ ou C. NSUInteger vous donnera un entier 64 bits non signé maintenant, mais si les choses changent, j'imagine qu'Apple mettra à jour cette macro (disons 128 bits à un moment donné, deviendra réelle)
Goles le
59

Source révisée utilisant 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: il semble que quelqu'un a édité ce code pour utiliser 'uint64_t' au lieu de 'unsigned long long'. Alors que dans un avenir prévisible cela devrait être très bien, ils ne sont pas les mêmes. 'uint64_t' est de 64 bits et le sera toujours. Dans 10 ans, «unsigned long long» pourrait être 128. c'est un petit point mais pourquoi j'ai utilisé unsignedLongLong.

David H
la source
Je n'ai pas d'expérience avec le nouveau système de comptage automatique, mais à quoi sert le __autoreleasing? Vous n'avez normalement pas besoin de libérer automatiquement le NSError renvoyé
le révérend
Cela pourrait aider: stackoverflow.com/questions/8862023/…
Fabian Kreiser
3
sur mon iPod Touch 4e génération exécutant iOS 5.1, NSFileSystemFreeSize rapporte toujours ~ 200 Mo de trop. J'imprime le contenu de l'ensemble de NSDictionary dans le débogueur ... NSFileSystemSize est correct cependant ... quelqu'un a une solution à ce problème?
Zennichimaro
@Zennichimaro: Avez-vous résolu votre problème? Je suis également confronté au même problème, obtenir 0,2 Go supplémentaire lorsque je vérifie l'espace libre sur l'iPad. L'iPad affiche 24,1 Go d'espace disponible, mais dans le code, il affiche 24,3 Go.
Sudheer Kumar Palchuri
1
@Diejmon vous ne pouvez pas demander à NSNumber une taille entière de ce type. C'est pourquoi pour de telles choses, je préfère une unité de taille de bit connue. Bien que techniquement je suis d'accord avec votre déclaration, j'ai déjà suffisamment d'avertissements pour gérer l'utilisation de NSInteger et formater les chaînes! 64 bits seront certainement assez de bits dans ma vie et la vôtre.
David H
34

J'ai écrit une classe pour obtenir la mémoire disponible / utilisée en utilisant Swift. Démo sur: https://github.com/thanhcuong1990/swift-disk-status
Swift 4 mis à jour.

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

}

Démo

obtenir l'état de l'espace disque avec Swift

Cuong Lam
la source
Avez-vous une idée de la raison pour laquelle MBFormatter est là? Il n'est utilisé nulle part.
Ben Sinclair
MBFormatter est une fonction pour convertir n'importe quelle valeur en valeur MB. Je ne l'utilise pas pour un projet de démonstration. Mais j'ai besoin d'un autre projet.
Cuong Lam
1
C'est génial de mettre dans une extension FileManager.
Leon
2
iTunes affiche 18,99 Go gratuits, mais j'obtiens 13,41 Go lorsque j'utilise les méthodes décrites. Est-ce que quelqu'un sait ce qui me manque?
Vitalii Boiarskyi
1
@CuongLam Les erreurs de décompression ne sont pas lancées et ne sont pas interceptées par do / catch. Un exemple de code source doit être écrit pour gérer correctement les erreurs. stackoverflow.com/questions/34628999/…
SafeFastExpressive
26

Si vous avez besoin d'une chaîne formatée avec une taille, vous pouvez jeter un œil à la belle bibliothèque sur 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
la source
2
Pour formater, on peut aussi utiliser NSBytCounterFormatter
Daniel Barden
Ceci est toujours sujet au même bug de + 200 Mo: stackoverflow.com/questions/9270027/...
Paulius Liekis
13

N'utilisez pas `` non signé '', ce ne sont que 32 bits qui déborderont au-delà de 4 Go, ce qui est inférieur à l'espace libre typique d'un iPad / iPhone. Utilisez unsigned long long (ou uint64_t) et récupérez la valeur du NSNumber sous la forme d'un entier 64 bits également à l'aide de unsignedLongLongValue.

Christopher Lloyd
la source
3
C'est mieux qu'un conseil - "C'est la loi" :-) Comme il l'a dit, le code original est tout simplement faux.
David H
13

Si vous cherchez à obtenir l'espace libre restant en utilisant Swift, c'est légèrement différent. Vous devez utiliser attributesOfFileSystemForPath () au lieu d'attributsOfItemAtPath ():

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: Mise à jour pour Swift 1.0
Edit 2: Mise à jour pour la sécurité, en utilisant la réponse de Martin R .
Edit 3: mis à jour pour Swift 2.0 (par dgellow )

RubenSandwich
la source
J'essayais d'utiliser cette réponse, mais elle ne se compilera pas sous GM ([NSObject: AnyObject]? N'a pas de membre nommé 'subscript'). Je pense que cela est dû au problème soulevé ici, mais je ne comprends pas comment faire fonctionner cette réponse dans ce contexte. Toute aide grandement appréciée.
Bryan Hanson
J'ai mis à jour la réponse pour travailler sur Swift 1.0 maintenant. Parce que attributesOfFileSystemForPath renvoie [NSObject: AnyObject]? vous avez besoin de cast vers NSDictionary? car il pourrait être nul et ensuite dérouler le dictionnaire afin de l'indiquer. (C'est un peu dangereux, donc je mettrai à jour la réponse un peu plus
tard
Merci pour la mise à jour. En fait, environ une heure avant votre réponse, j'étais allé de l'avant et formulé la question comme une nouvelle question ici . Il y a une réponse là-bas maintenant, mais comme cette méthode de traitement des options est un peu opaque pour moi, j'aimerais voir une autre approche à votre convenance. Salue ta sœur Rachel.
Bryan Hanson
Bryan, je suggérerais la première réponse à votre question, car c'est un bon mélange de sécurité et de clarté. Je ne suis pas sûr de pouvoir donner une meilleure réponse que celle-là. Les options peuvent être déroutantes au début, je suggère fortement de lire la section des manuels Swift sur les options, c'est assez bon.
RubenSandwich
Très apprécié, je vais revoir ce manuel et j'ai également trouvé de bonnes questions SO. Bryan
Bryan Hanson
9

Voici ma réponse et pourquoi c'est mieux.

Réponse (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
}

Réponse (Objectif-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;
}

Pourquoi c'est mieux:

  • Utilise la bibliothèque intégrée de Cocoa NSByteCountFormatter , ce qui signifie pas de calculs manuels fous d'octets en gigaoctets. Apple fait cela pour vous!
  • Facilement traduisible: NSByteCountFormatterfait cela pour vous. Par exemple, lorsque la langue de l'appareil est réglée sur l'anglais, la chaîne lira 248,8 Mo mais lira 248,8 Mo lorsqu'elle est réglée sur le français, et cetera pour les autres langues.
  • Une valeur par défaut est donnée en cas d'erreur.
ChrisJF
la source
1
@JuanBoero Publié dans Swift 3.1 (enfin)!
ChrisJF
7

Précision importante (du moins pour moi). Si je connecte mon iPod à mon Mac, ce sont les informations affichées par l'application iTunes.

Informations sur la mémoire de l'iPod depuis l'application iTunes

Lorsque j'utilise le code ci-dessus:

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

Le countStyle NSByteCountFormatterCountStyleFile montre-moi: 17,41 Go

Le countStyle NSByteCountFormatterCountStyleBinary montre-moi: 16,22 Go

16,22 Go ( NSByteCountFormatterCountStyleBinary ) C'est EXACTEMENT le numéro que l'application iTunes me montre lorsque je connecte mon iPod à mon Mac.

Markus
la source
peut-être que le fichier est uniquement pour les fichiers MAC et non pour iOS?
João Nunes
c'est la même quantité d'octets multipliée par 1000 (Ko puis Mo puis Go) contre 1024.
Jim75
7

Mettez à jour avec une nouvelle API précise pour obtenir la taille disponible sur le disque disponible dans iOS11. Voici la description de la nouvelle clé de ressource 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

J'ai comparé les résultats de la clé " FileAttributeKey.systemFreeSize " et de la clé " URLResourceKey.volumeAvailableCapacityForImportantUsageKey " et j'ai trouvé les résultats renvoyés sous la forme " volumeAvailableCapacityForImportantUsageKey " correspondant exactement au stockage disponible affiché sur l'interface utilisateur. Comparaison de l'espace disque disponible disponible Voici la mise en œuvre rapide:

class var freeDiskSpaceInBytesImportant:Int64 {
    get {
        do {
            return try URL(fileURLWithPath: NSHomeDirectory() as String).resourceValues(forKeys: [URLResourceKey.volumeAvailableCapacityForImportantUsageKey]).volumeAvailableCapacityForImportantUsage!
        } catch {
            return 0
        }
    }
}
Evilisn Jiang
la source
D'où vient «l'usage opportuniste» sur votre capture d'écran?
rshev
Je l' ai trouvé, volumeAvailableCapacityForOpportunisticUsageKey.
rshev
Oui rshev, volumeAvailableCapacityForOpportunisticUsageKey obtient «une utilisation opportuniste» sur ma capture d'écran
Evilisn Jiang
pour voir la taille de stockage disponible dois-je interroger avec NSHomeDirectory()ou NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true). Y a-t-il une différence en utilisant ces deux?
Suryakant Sharma
7

Vous pouvez trouver une autre solution en utilisant Swift 4 etextension qui vous donne une bonne option.

Voici l' UIDeviceextension.

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

}

Et exemple d'utilisation:

UIDevice.current.totalDiskSpaceInBytes()
UIDevice.current.totalDiskSpace()
UIDevice.current.freeDiskSpaceInBytes()
UIDevice.current.freeDiskSpace()
UIDevice.current.usedDiskSpaceInBytes()
UIDevice.current.usedDiskSpace()
abdullahselek
la source
Ne pas utiliser à la !place mettre un guarden sécurité typecastingou nilvérifier.
TheTiger
Merci pour vos commentaires @TheTiger.
abdullahselek
3

Pour iOS> = 6.0, vous pouvez utiliser le nouveau NSByteCountFormatter. Ce code obtient le nombre d'octets libres restants sous forme de chaîne formatée.

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
la source
2

Le code suivant est l'implémentation de la version Swift 3.0 de la réponse précédemment fournie par 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
la source
Pourquoi est-ce que cela renvoie plus que les informations sur l'espace disque disponible de l'iPhone. Lorsque le menu de configuration des iPhones indique 998 Mo, cela renvoie 1,2 Go
Hope
1

pour Swift comme extension 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
        }
    }
}

Comment utiliser:

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

La sortie sera:

Memory 9656 of 207694 Mb available.
ale_stro
la source
1

Je sais que cet article est un peu vieux, mais je pense que cette réponse peut aider quelqu'un. Si vous voulez connaître l'espace disque utilisé / libre / total sur l'appareil, vous pouvez utiliser Luminous . C'est écrit en Swift. Vous n'avez qu'à appeler:

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

ou

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

Implémentation rapide du code ci-dessus: -

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


}

Appelez-le de n'importe quelle autre 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");
    }

Lors du test de la valeur renvoyée, elle est identique à celle affichée par d'autres applications. Au moins dans mon iPhone 6S +. C'est juste la mise en œuvre rapide de la réponse ci-dessus. Et pour moi, la réponse acceptée n'a pas fonctionné.

Bikram
la source
0

Réponse de ChrisJF dans la version 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
la source
0

Extension Swift 5 pour FileManagerune gestion correcte des erreurs et aucune conversion automatique de chaîne (convertissez le nombre d'octets en chaîne comme vous préférez). Suit également FileManagerla dénomination.

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

Exemple d'utilisation:

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)")
}
ivanzoïde
la source