Як виявити загальний доступний / вільний простір на диску на пристрої 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;
}


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


Сподіваюся, посилання
stackoverflow

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 під час підключення пристрою до машини.


4
Перетворення на поплавок може дати неточні результати вище приблизно 2 Гб. Якщо вам потрібно мати справу з дійсно великими розмірами файлів, замість цього використовуйте подвійний або довгий подвійний.
Ясен

Як вказував Еш, цей метод має неточний результат. У моєму iPad 2, об’ємом 64 Гб, він виходить з ладу на +0,25 Гб ... Метод, наведений нижче, опублікований Девідом Н, має точний результат при використанні uint64_t vars.
Леандро Алвеш

3
Фрагмент коду було відредаговано для відображення пропозицій від @David H, як показано нижче.
Code.Warrior

4
+200 Мб - це не проблема. У налаштуваннях у мене є "0 байт" вільного простору. І коли я заходжу та використовую свою програму, цей метод повідомляє про 150 Мб вільного місця. Потім я заповнюю це місце, що залишилося, і лише тоді додаток виходить з ладу. Тому я б сказав, що цей метод дає вам більш правильну інформацію, ніж те, що ви бачите в налаштуваннях.
ancajic

4
Чому ніхто не використовує NSUIntegerзамість таких матеріалів, як uint64_t? Ми пишемо Obj-C, а не C ++ чи C. NSUInteger дасть вам 64-розрядне ціле без підпису, але якщо щось станеться, я думаю, що Apple оновить цей макрос (скажімо, 128 біт у якийсь момент стане справжнім)
Голз

59

Переглянуте джерело, використовуючи неподписані довго:

- (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: здається, хтось редагував цей код, використовуючи 'uint64_t' замість 'unsigned long long'. Хоча в осяжному майбутньому це має бути добре, вони не однакові. 'uint64_t' - це 64 біти, і це завжди буде. Через 10 років "неподписаний довгий" може бути 128. Це невеликий момент, але чому я використовував unsignedLongLong.


Я не маю досвіду роботи з новою системою автоматичного підрахунку, але для чого __авторелізинг? Зазвичай вам не потрібно автоматично випускати повернувся NSError
преподобний

Це може допомогти: stackoverflow.com/questions/8862023/…
Fabian Kreiser

3
на моєму iPod Touch 4-го покоління під керуванням iOS 5.1, NSFileSystemFreeSize все ще повідомляє ~ 200 Мбіт занадто багато. Я роздруковую вміст всього NSDictionary в налагоджувальній ... NSFileSystemSize правильний, хоча ... хтось має рішення для цієї проблеми?
Zennichimaro

@Zennichimaro: Ви вирішили свою проблему? Я також стикаюся з тією ж проблемою, отримуючи 0,2 ГБ додатково, коли я перевіряю вільний простір в iPad. iPad показує 24,1 ГБ вільного місця, але в коді він показує 24,3 ГБ.
Sudheer Kumar Palchuri

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 - це функція перетворення будь-якого значення у значення MB. Я не використовую це для демонстраційного проекту. Але мені потрібен інший проект.
Куонг Лам

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

2
Для форматування також можна використовувати NSBytCounterFormatter
Даніель Барден

Це по - , як і раніше схильна до такої ж + 200MB помилку: stackoverflow.com/questions/9270027 / ...
Паулюс Liekis

13

Не використовуйте "без підпису", це лише 32 біти, які переповнюватимуть минулі 4 Гб, що менше типового вільного простору для iPad / iPhone. Використовуйте неподписані довгі довгі (або uint64_t), і отримайте значення з NSNumber як 64-бітовий int, використовуючи unsignedLongLongValue.


3
Це краще, ніж підказка - "Його закон" :-) Як він сказав, оригінальний код просто невірний.
Девід Н

13

Якщо ви шукаєте, щоб отримати решту вільного місця за допомогою Swift, це трохи інше. Вам потрібно використовувати attributesOfFileSystemForPath () замість attributesOfItemAtPath ():

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

Редагування: оновлено для Swift 1.0
Edit 2: Оновлення для безпеки, використовуючи відповідь Мартіна R в .
Редагування 3: оновлено для Swift 2.0 (від dgellow )


Я намагався використати цю відповідь, але вона не буде компілюватися під GM ([NSObject: AnyObject]? Не має члена з іменем "subcript"). Я думаю, що це пов'язано з проблемою, яку тут піднімають, але я не розумію, як змусити цю відповідь працювати в цьому контексті. Будь-яка допомога дуже вдячна.
Брайан Гансон

Я оновив відповідь, щоб зараз працювати над Swift 1.0. Тому що attributesOfFileSystemForPath повертає [NSObject: AnyObject]? вам потрібно передати NSDictionary? як це може бути нульовим, а потім розгорніть словник, щоб підписати його. (Це трохи небезпечно, тому я останній час
оновлю

Дякуємо за оновлення. Як виявляється, за годину до Вашої відповіді я пішов далі і сформулював це питання як свіже питання тут . Зараз є відповідь, але оскільки цей спосіб поводження з необов'язковими для мене дещо непрозорим, я хотів би побачити інший підхід для вашої зручності. Подякуйте за вашу сестру Рейчел.
Брайан Гансон

Брайан, я запропонував би першу відповідь на ваше відповідне запитання, оскільки це гарна суміш безпеки та ясності. Я не впевнений, що міг би дати кращу відповідь, ніж той. Необов'язково спочатку може бути заплутаним, я настійно пропоную прочитати розділ посібників Swift про додаткові додатки, це дуже добре.
RubenSandwich

Дуже вдячний, я ще раз перегляну цей посібник, і я знайшов кілька хороших запитань щодо SO. Брайан
Брайан Гансон

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
}

Відповідь (Ціль-С):

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

Чому краще:

  • Використовує вбудовану в бібліотеку какао NSByteCountFormatter , тобто не має шалених ручних обчислень від байтів до гігабайт. Apple робить це за вас!
  • Легко перекладається: NSByteCountFormatterробить це за вас. Напр., Коли для мови пристрою встановлено значення англійською мовою, рядок буде читати 248,8 МБ, але буде прочитати 248,8 МО, якщо встановлено на французьку, та ін. Для інших мов.
  • У разі помилки задається значення за замовчуванням.

1
@JuanBoero Опубліковано в Swift 3.1 (нарешті)!
ChrisJF

7

Важливе уточнення (принаймні для мене). Якщо я підключаю iPod до свого Mac, це інформація, показана додатком iTunes.

Інформація про пам'ять 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.


можливо, Файл призначений лише для файлів MAC, а не для iOS?
Жоао Нунес

це така ж кількість байтів, помножена на 1000 (КБ, то МБ, то ГБ) проти 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 " точно відповідає доступному сховищу , показаному на UI. Доступне порівняння вільного місця на диску Ось швидка реалізація:

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

Звідки на екрані екрана "опортуністичне використання"?
ршев

Знайшов, volumeAvailableCapacityForOpportunisticUsageKey.
ршев

Так 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()

Не використовуйте !натомість поставте 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

}

Чому це повернення більше інформації про доступний дисковий простір iPhone. Коли в меню настройки iPhones говориться про 998 Мб, це повертає 1,2 ГБ
Надія

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.

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

Розширення 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)")
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.