Как определить общее доступное / свободное дисковое пространство на устройстве iPhone / iPad?

147

Я ищу лучший способ для определения доступного / свободного дискового пространства на устройстве iPhone / iPad.
В настоящее время я использую NSFileManager для обнаружения дискового пространства. Ниже приведен фрагмент кода, который выполняет эту работу за меня:

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


Я прав с приведенным выше фрагментом? или есть ли лучший способ узнать общее доступное / свободное дисковое пространство.
Я должен определить общее свободное место на диске, так как мы должны запретить нашему приложению выполнять синхронизацию в сценарии с нехваткой места на диске.

Code.Warrior
источник
Надеюсь, вам поможет ссылка stackoverflow ..
senthilMuthu
1
Похоже, что код, который он использует в своем вопросе, лучше, чем код в указанной вами ссылке (он просто проверяет один каталог, а не просматривает все подкаталоги в «/»)
Кендалл Хельмштеттер Гелнер
Спасибо Михаилу за ссылку. Но я ищу общее доступное / свободное дисковое пространство на устройстве iPhone / iPad, а не только конкретную папку. Например, на iPhone емкостью 32 ГБ, если общий доступный / свободный размер составляет 28 ГБ, я смогу обнаружить это программно.
Code.Warrior
Я надеюсь, что эта ссылка поможет: jayprakashdubey.blogspot.in/2014/07/…
Jayprakash Dubey

Ответы:

152

ОБНОВЛЕНИЕ : так как после этого ответа прошло много времени и были добавлены новые методы / API, пожалуйста, проверьте обновленные ответы ниже для Swift и т. Д .; Поскольку я сам ими не пользовался, я не могу за них поручиться.

Оригинальный ответ : я нашел следующее решение, работающее на меня:

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

Он возвращает мне именно тот размер, который отображает iTunes, когда устройство подключено к машине.

Code.Warrior
источник
4
Преобразование в число с плавающей запятой может дать неточные результаты выше 2 ГБ. Если вам нужно иметь дело с действительно большими размерами файлов, используйте вместо этого двойной или длинный двойной.
Пепел
Как указывает Эш, этот метод имеет неточный результат. В моем iPad 2 с 64 ГБ происходит сбой на +0,25 ГБ ... Метод ниже, опубликованный Дэвидом Х, дает точный результат при использовании переменных uint64_t.
Леандро Алвес
3
Фрагмент кода был отредактирован, чтобы отразить предложения @David H, как показано ниже.
Code.Warrior
4
+200 МБ это не проблема. В настройках у меня есть "0 байт" свободного места. И когда я вхожу и использую свое приложение, этот метод сообщает о 150 МБ свободного места. Затем я заполняю это оставшееся место, и только тогда приложение вылетает. Поэтому я бы сказал, что этот метод дает вам более правильную информацию, чем то, что вы видите в настройках.
ancajic
4
Почему никто не использует NSUIntegerвместо таких вещей, как uint64_t? Мы пишем Obj-C, а не C ++ или C. NSUInteger теперь выдаст вам 64-разрядное целое число без знака, но если что-то изменится, я думаю, что Apple обновит этот макрос (скажем, 128-битный в какой-то момент станет реальностью)
Гоулс
59

Пересмотренный источник с использованием 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;
}

РЕДАКТИРОВАТЬ: кажется, кто-то отредактировал этот код, чтобы использовать «uint64_t» вместо «unsigned long long». Хотя в обозримом будущем это должно быть просто прекрасно, они не одинаковы. 'uint64_t' является 64-битным и всегда будет таким. Через 10 лет «unsigned long long» может быть 128. Это небольшой вопрос, но почему я использовал unsignedLongLong.

Дэвид Х
источник
У меня нет опыта работы с новой системой автоматического подсчета, но зачем нужен __autoreleasing? Обычно вам не нужно автоматически выпускать возвращенную ошибку NSE
Преподобный
Это может помочь: stackoverflow.com/questions/8862023/…
Фабиан Крейзер
3
на моем iPod Touch 4-го поколения под управлением iOS 5.1 NSFileSystemFreeSize по-прежнему сообщает о ~ 200 МБ слишком много. Я распечатываю содержимое всего NSDictionary в отладчике ... NSFileSystemSize является правильным, хотя ... у кого-нибудь есть решение этой проблемы?
Зеннихимаро
@Zennichimaro: Вы решили свою проблему? Я также сталкиваюсь с той же проблемой, получая дополнительно 0,2 ГБ при проверке свободного места в iPad. iPad показывает 24,1 ГБ свободного места, но в коде он показывает 24,3 ГБ.
Судхер Кумар Пальчури
1
@Diejmon, вы не можете запросить NSNumber для целочисленного размера этого типа. Вот почему для таких вещей я предпочитаю единицу измерения известного размера. Хотя технически я согласен с вашим утверждением, у меня уже достаточно предупреждений, чтобы иметь дело с использованием NSInteger и форматирования строк! 64 бита наверняка хватит на мою и вашу жизнь.
Дэвид Х
34

Я написал класс, чтобы получить доступную / использованную память, используя Swift. Демонстрация по адресу: https://github.com/thanhcuong1990/swift-disk-status
Swift 4 обновлена.

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

}

демонстрация

получить статус дискового пространства с Swift

Куонг Лам
источник
У вас есть идея, почему MBFormatter существует? Это нигде не используется.
Бен Синклер
MBFormatter - это функция для преобразования любого значения в значение в МБ. Я не использую это для демонстрационного проекта. Но мне нужен другой проект.
Куонг Лам
1
Это здорово, чтобы положить в расширение FileManager.
Леон
2
iTunes показывает 18,99 ГБ бесплатно, но я получаю 13,41 ГБ при использовании описанных методов. Кто-нибудь знает, что я скучаю?
Виталий Боярский
1
@CuongLam Ошибки распаковки не генерируются и не перехватываются do / catch. Образец исходного кода должен быть написан для правильной обработки ошибок. stackoverflow.com/questions/34628999/…
SafeFastExpressive
26

Если вам нужна отформатированная строка с размером, вы можете взглянуть на красивую библиотеку на 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
источник
2
Для форматирования также можно использовать NSBytCounterFormatter
Даниэль Барден,
Это все еще подвержено той же ошибке + 200
МБ
13

Не используйте «unsigned», это всего лишь 32 бита, которые будут переполнены после 4 ГБ, что меньше, чем обычное свободное пространство iPad / iPhone. Используйте unsigned long long (или uint64_t) и извлеките значение из NSNumber как 64-разрядного типа int, также используя unsignedLongLongValue.

Кристофер Ллойд
источник
3
Это лучше, чем совет - «Это закон» :-) Как он сказал, оригинальный код просто неверен.
Дэвид Х
13

Если вы хотите получить оставшееся свободное пространство с помощью Swift, это немного отличается. Вам нужно использовать attributeOfFileSystemForPath () вместо 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: Обновление для Swift 1.0
Edit 2: Обновление для безопасности, используя ответ Мартина R в .
Редактировать 3: Обновлено для Swift 2.0 (от dgellow )

RubenSandwich
источник
Я пытался использовать этот ответ, но он не будет компилироваться под GM ([NSObject: AnyObject]? Не имеет члена с именем 'subscript'). Я думаю, что это связано с проблемой, поднятой здесь, но я не понимаю, как заставить этот ответ работать в этом контексте. Любая помощь с благодарностью.
Брайан Хэнсон
Я обновил ответ для работы на Swift 1.0 сейчас. Потому что attributeOfFileSystemForPath возвращает [NSObject: AnyObject]? вам нужно привести к NSDictionary? как это может быть ноль, а затем разверните словарь, чтобы добавить его. (Это немного небезопасно, поэтому я
обновлю
Спасибо за обновление. Оказывается, примерно за час до вашего ответа я сформулировал проблему как свежий вопрос здесь . Там сейчас есть ответ, но так как этот метод работы с опционами немного непрозрачен для меня, я хотел бы увидеть другой подход для вашего удобства. Передайте привет вашей сестре Рейчел.
Брайан Хэнсон
Брайан, я бы предложил первый ответ на ваш ответ на вопрос, так как это хорошее сочетание безопасности и ясности. Я не уверен, что мог бы дать лучший ответ, чем этот. Опционы могут поначалу сбивать с толку, я настоятельно рекомендую прочитать раздел руководств Swift по опциям, это довольно хорошо.
RubenSandwich
Буду признателен, я еще раз посмотрю это руководство и также нашел несколько хороших вопросов. Брайан
Брайан Хэнсон
9

Вот мой ответ и почему это лучше.

Ответ (Свифт):

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
}

Ответ (Цель-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;
}

Почему лучше

  • Использует встроенную библиотеку Cocoa NSByteCountFormatter, что означает отсутствие сумасшедших ручных вычислений от байтов до гигабайт. Apple делает это для вас!
  • Легко переводится: NSByteCountFormatterделает это за вас. Например, когда язык устройства установлен на английский, строка будет иметь значение 248,8 МБ, но будет иметь значение 248,8 Мо при установке на французский и т. Д. Для других языков.
  • Значение по умолчанию дается в случае ошибки.
ChrisJF
источник
1
@JuanBoero Опубликовано в Swift 3.1 (наконец-то)!
ChrisJF
7

Важное уточнение (по крайней мере для меня). Если я подключу свой iPod к своему Mac, это информация, отображаемая iTunes App.

Информация о памяти iPod из приложения iTunes

Когда я использую приведенный выше код:

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

CountStyle NSByteCountFormatterCountStyleFile показать мне: 17,41 ГБ

CountStyle NSByteCountFormatterCountStyleBinary показать мне: 16,22 ГБ

16,22 GB ( NSByteCountFormatterCountStyleBinary ) Это ТОЧНО число , что ITunes App показать мне , когда я подключить айпод к моему Mac.

Markus
источник
может быть, файл предназначен только для файлов MAC, а не для iOS?
Жоау Нуньес
это то же самое количество байт умножаются в 1000 (KB затем MB затем GB) по сравнению с 1024.
Jim75
7

Обновите с новым точным API, чтобы получить доступный размер на диске, доступном в iOS11. Вот описание для нового ключа ресурса 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

Я сопоставил результаты ключа « FileAttributeKey.systemFreeSize » и ключа « URLResourceKey.volumeAvailableCapacityForImportantUsageKey » и обнаружил, что возвращенная форма результатов « volumeAvailableCapacityForImportantUsageKey » точно соответствует доступному хранилищу, отображаемому в пользовательском интерфейсе. Сравнение свободного дискового пространства Вот быстрая реализация:

class var freeDiskSpaceInBytesImportant:Int64 {
    get {
        do {
            return try URL(fileURLWithPath: NSHomeDirectory() as String).resourceValues(forKeys: [URLResourceKey.volumeAvailableCapacityForImportantUsageKey]).volumeAvailableCapacityForImportantUsage!
        } catch {
            return 0
        }
    }
}
Evilisn Jiang
источник
Откуда происходит «оппортунистическое использование» на вашем скриншоте?
rshev
Нашел это volumeAvailableCapacityForOpportunisticUsageKey.
rshev
Да rshev, volumeAvailableCapacityForOpportunisticUsageKey получает «« оппортунистическое использование »на моем скриншоте
Evilisn Jiang
чтобы увидеть доступный размер хранилища, я должен запросить с помощью NSHomeDirectory()или NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true). Есть ли разница, используя эти два?
Сурьякант Шарма
7

Вы можете найти другое решение , с помощью Swift 4 и extensionкоторая дает вам вариант хороший.

Вот UIDeviceрасширение.

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

}

И пример использования:

UIDevice.current.totalDiskSpaceInBytes()
UIDevice.current.totalDiskSpace()
UIDevice.current.freeDiskSpaceInBytes()
UIDevice.current.freeDiskSpace()
UIDevice.current.usedDiskSpaceInBytes()
UIDevice.current.usedDiskSpace()
abdullahselek
источник
Не используйте !вместо этого, чтобы положить guardв сейф typecastingили nilпроверить.
TheTiger
Спасибо за ваши комментарии @TheTiger.
abdullahselek
3

Для iOS> = 6.0 вы можете использовать новое NSByteCountFormatter. Этот код получает количество свободных байтов, оставшихся в виде отформатированной строки.

NSError *error = nil;
NSArray * const paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSDictionary * const pathAttributes = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[paths firstObject] error:&error];
NSAssert(pathAttributes, @"");
NSNumber * const fileSystemSizeInBytes = [pathAttributes objectForKey: NSFileSystemFreeSize];
const long long numberOfBytesRemaining = [fileSystemSizeInBytes longLongValue];
NSByteCountFormatter *byteCountFormatter = [[NSByteCountFormatter alloc] init];
NSString *formattedNmberOfBytesRemaining = [byteCountFormatter stringFromByteCount:numberOfBytesRemaining];
Роберт
источник
2

Следующий код является реализацией версии Swift 3.0 ответа, ранее предоставленного 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
источник
Почему это возвращает больше информации о доступном дисковом пространстве iPhone. Когда в меню настроек iPhone указано 998 МБ, возвращается 1,2 ГБ
Hope
1

для Swift как расширение 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
        }
    }
}

Как пользоваться:

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

Выход будет:

Memory 9656 of 207694 Mb available.
ale_stro
источник
1

Я знаю, что этот пост немного стар, но я думаю, что этот ответ может кому-то помочь. Если вы хотите узнать используемое / свободное / общее дисковое пространство на устройстве, вы можете использовать Luminous . Это написано на Swift. Вам остается только позвонить:

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

или

Luminous.System.Disk.freeSpaceInBytes()
Luminous.System.Disk.usedSpaceInBytes()
Андреа Марио Луфино
источник
1

Быстрая реализация приведенного выше кода: -

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


}

Назовите это из любого другого класса.

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

При тестировании возвращаемого значения оно совпадает с показанным в других приложениях. По крайней мере, в моем iPhone 6S +. Это просто быстрая реализация показанного выше ответа. И для меня принятый ответ не сработал.

Бикрам
источник
0

Ответ ChrisJF в версии Swift 2.1 :

func freeSpaceInBytes() -> NSString{

    var remainingSpace = NSLocalizedString("Unknown", comment: "The remaining free disk space on this device is unknown.")

    do {

        let dictionary =  try NSFileManager.defaultManager().attributesOfFileSystemForPath(NSHomeDirectory())
        freeSpaceSize = (dictionary[NSFileSystemFreeSize]?.longLongValue)!
        remainingSpace = NSByteCountFormatter.stringFromByteCount(freeSpaceSize, countStyle: NSByteCountFormatterCountStyle.File)

    }
    catch let error as NSError {

        error.description
        NSLog(error.description)

    }

    return remainingSpace

}
Хуан Боэро
источник
0

Если вы хотите сэкономить время, используйте следующую библиотеку CocoaPod. Я не использовал это, но похоже, что это должно работать.

https://cocoapods.org/pods/SystemServices

arango_86
источник
0

Расширение Swift 5 для FileManagerс правильной обработкой ошибок и без автоматического преобразования строк (конвертируйте количество байтов в строку по своему усмотрению). Также следует FileManagerнаименование.

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

Пример использования:

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
источник