Bagaimana cara mendeteksi total ruang disk kosong yang tersedia / pada perangkat iPhone / iPad?

147

Saya mencari cara yang lebih baik untuk mendeteksi ruang disk yang tersedia / kosong di perangkat iPhone / iPad secara terprogram.
Saat ini saya menggunakan NSFileManager untuk mendeteksi ruang disk. Berikut ini cuplikan kode yang berfungsi untuk saya:

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


Apakah saya benar dengan cuplikan di atas? atau apakah ada cara yang lebih baik untuk mengetahui total ruang disk yang tersedia / bebas.
Saya sudah mendeteksi total ruang disk kosong, karena kami harus mencegah aplikasi kami melakukan sinkronisasi dalam skenario ruang disk rendah.

Kode. Prajurit
sumber
Saya harap tautan stackoverflow akan membantu Anda ..
senthilMuthu
1
Sepertinya kode yang ia gunakan dalam pertanyaannya lebih baik daripada kode di tautan yang Anda berikan (dia hanya memeriksa satu direktori alih-alih melintasi semua sub-direktori di bawah "/")
Kendall Helmstetter Gelner
Terima kasih Mikhail untuk tautannya. Tapi saya mencari total ruang disk yang tersedia / gratis pada perangkat iPhone / iPad, bukan hanya folder tertentu. Sebagai contoh, pada iPhone 32GB, jika ukuran total yang tersedia / gratis adalah 28GB, saya harus dapat mendeteksi itu secara terprogram.
Code.Warrior
Saya harap tautan ini membantu: jayprakashdubey.blogspot.in/2014/07/…
Dubey

Jawaban:

152

UPDATE : Karena banyak waktu telah berlalu setelah jawaban ini dan metode / API baru telah ditambahkan, silakan periksa jawaban yang diperbarui di bawah untuk Swift dll; Karena saya sendiri belum menggunakannya, saya tidak bisa menjaminnya.

Jawaban asli : Saya menemukan solusi berikut ini berfungsi untuk saya:

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

Ini mengembalikan saya persis ukuran yang ditampilkan iTunes ketika perangkat terhubung ke mesin.

Kode. Prajurit
sumber
4
Konversi ke pelampung dapat memberikan hasil yang tidak akurat di atas sekitar 2GB. Jika Anda perlu menangani ukuran file yang sangat besar, gunakan ganda atau panjang ganda sebagai gantinya.
Ash
Seperti yang ditunjukkan oleh Ash, metode ini memiliki hasil yang tidak akurat. Di iPad 2 saya, dengan 64GB, gagal +0,25 GB ... Metode di bawah ini, yang diposting oleh David H, memiliki hasil yang akurat ketika menggunakan uint64_t vars.
Leandro Alves
3
Cuplikan kode telah diedit untuk mencerminkan saran dari @ David H seperti yang ditunjukkan di bawah ini.
Code.Warrior
4
+200 MB tidak masalah. Dalam Pengaturan saya memiliki "0 byte" ruang yang tersedia. Dan ketika saya masuk dan menggunakan aplikasi saya, metode ini melaporkan ruang kosong 150mb. Lalu saya mengisi ruang yang tersisa ini dan hanya kemudian aplikasi crash. Jadi saya akan mengatakan bahwa metode ini memberi Anda informasi yang lebih benar daripada yang Anda lihat di Pengaturan.
ancajic
4
Mengapa tidak ada yang menggunakan, NSUIntegerbukan hal-hal seperti uint64_t? Kami sedang menulis Obj-C, bukan C ++ atau C. NSUInteger akan memberi Anda integer 64 bit yang tidak ditandatangani sekarang, tetapi jika terjadi perubahan, saya membayangkan Apple akan memperbarui Makro itu (katakanlah 128 bit pada suatu titik, menjadi nyata)
Goles
59

Sumber yang direvisi menggunakan unsigned, lama:

- (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: tampaknya seseorang mengedit kode ini untuk menggunakan 'uint64_t' alih-alih 'unsigned long long'. Sementara di masa mendatang ini seharusnya baik-baik saja, mereka tidak sama. 'uint64_t' adalah 64 bit dan akan selalu seperti itu. Dalam 10 tahun 'unsigned long long' mungkin 128. ini adalah poin kecil tapi mengapa saya menggunakan unsignedLongLong.

David H
sumber
Saya tidak memiliki pengalaman dengan sistem penghitungan otomatis baru tetapi untuk apa __autoreleasing? Anda biasanya tidak perlu melakukan autorelease NSError yang dikembalikan
Pendeta
Ini mungkin membantu: stackoverflow.com/questions/8862023/…
Fabian Kreiser
3
di iPod Touch 4th Gen saya yang menjalankan iOS 5.1, NSFileSystemFreeSize masih melaporkan ~ 200 MB terlalu banyak. Saya mencetak konten seluruh NSDictionary di debugger ... NSFileSystemSize sudah benar ... ada yang punya solusi untuk masalah ini?
Zennichimaro
@Zennichimaro: Apakah Anda memperbaiki masalah Anda? Saya juga menghadapi masalah yang sama, mendapatkan ekstra 0,2 GB ketika saya memeriksa ruang kosong di iPad. iPad menunjukkan ruang yang tersedia 24,1 GB tetapi dalam kode itu menunjukkan 24,3 GB.
Sudheer Kumar Palchuri
1
@Dmonjmon Anda tidak dapat meminta NSNumber untuk ukuran integral dari tipe ini. Inilah sebabnya mengapa untuk hal-hal seperti itu saya lebih suka unit ukuran bit yang dikenal. Meskipun secara teknis saya setuju dengan pernyataan Anda, saya sudah memiliki cukup peringatan untuk berurusan dengan menggunakan NSInteger dan memformat string! 64 bit akan menjadi bit yang cukup pasti dalam hidup saya dan Anda.
David H
34

Saya telah menulis sebuah kelas untuk mendapatkan memori yang digunakan / digunakan menggunakan Swift. Demo di: https://github.com/thanhcuong1990/swift-disk-status
Swift 4 diperbarui.

import UIKit

class DiskStatus {

    //MARK: Formatter MB only
    class func MBFormatter(_ bytes: Int64) -> String {
        let formatter = ByteCountFormatter()
        formatter.allowedUnits = ByteCountFormatter.Units.useMB
        formatter.countStyle = ByteCountFormatter.CountStyle.decimal
        formatter.includesUnit = false
        return formatter.string(fromByteCount: bytes) as String
    }


    //MARK: Get String Value
    class var totalDiskSpace:String {
        get {
            return ByteCountFormatter.string(fromByteCount: totalDiskSpaceInBytes, countStyle: ByteCountFormatter.CountStyle.file)
        }
    }

    class var freeDiskSpace:String {
        get {
            return ByteCountFormatter.string(fromByteCount: freeDiskSpaceInBytes, countStyle: ByteCountFormatter.CountStyle.file)
        }
    }

    class var usedDiskSpace:String {
        get {
            return ByteCountFormatter.string(fromByteCount: usedDiskSpaceInBytes, countStyle: ByteCountFormatter.CountStyle.file)
        }
    }


    //MARK: Get raw value
    class var totalDiskSpaceInBytes:Int64 {
        get {
            do {
                let systemAttributes = try FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory() as String)
                let space = (systemAttributes[FileAttributeKey.systemSize] as? NSNumber)?.int64Value
                return space!
            } catch {
                return 0
            }
        }
    }

    class var freeDiskSpaceInBytes:Int64 {
        get {
            do {
                let systemAttributes = try FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory() as String)
                let freeSpace = (systemAttributes[FileAttributeKey.systemFreeSize] as? NSNumber)?.int64Value
                return freeSpace!
            } catch {
                return 0
            }
        }
    }

    class var usedDiskSpaceInBytes:Int64 {
        get {
            let usedSpace = totalDiskSpaceInBytes - freeDiskSpaceInBytes
            return usedSpace
        }
    }

}

Demo

dapatkan status ruang disk dengan Swift

Cuong Lam
sumber
Apakah Anda tahu mengapa MBFormatter ada di sana? Itu tidak digunakan di mana pun.
Ben Sinclair
MBFormatter adalah fungsi untuk mengubah nilai apa pun menjadi nilai MB. Saya tidak menggunakannya untuk proyek demo. Tapi saya butuh proyek lain.
Cuong Lam
1
Ini bagus untuk dimasukkan ke dalam ekstensi FileManager.
Leon
2
iTunes menunjukkan 18,99 GB gratis tetapi saya mendapatkan 13,41 GB ketika saya menggunakan metode yang dijelaskan. Adakah yang tahu apa yang saya lewatkan?
Vitalii Boiarskyi
1
@CuongLam Kesalahan unwrapping tidak dibuang dan tidak tertangkap oleh do / catch. Kode sumber sampel harus ditulis untuk menangani kesalahan dengan benar. stackoverflow.com/questions/34628999/…
SafeFastExpressive
26

Jika Anda membutuhkan string yang diformat dengan ukuran Anda dapat melihat perpustakaan yang bagus di 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
sumber
2
Untuk memformat, orang juga dapat menggunakan NSBytCounterFormatter
Daniel Barden
Ini masih rentan terhadap bug + 200MB yang sama: stackoverflow.com/questions/9270027/…
Paulius Liekis
13

Jangan gunakan 'unsigned', hanya 32 bit yang akan melebihi 4GB, yang kurang dari ruang bebas khas iPad / iPhone. Gunakan unsigned long long (atau uint64_t), dan ambil nilai dari NSNumber sebagai 64-bit int juga menggunakan unsignedLongLongValue.

Christopher Lloyd
sumber
3
Lebih baik daripada tip - "Ini Hukumnya" :-) Seperti yang dia katakan, kode aslinya salah.
David H
13

Jika Anda mencari untuk mendapatkan ruang kosong yang tersisa menggunakan Swift itu sedikit berbeda. Anda perlu menggunakan atributOfFileSystemForPath () alih-alih atributOfItemAtPath ():

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: Diperbarui untuk Swift 1.0
Edit 2: Diperbarui untuk keselamatan, menggunakan jawaban Martin R .
Sunting 3: Diperbarui untuk Swift 2.0 (oleh dgellow )

RubenSandwich
sumber
Saya mencoba menggunakan jawaban ini, tetapi tidak dapat dikompilasi di bawah GM ([NSObject: AnyObject]? Tidak memiliki anggota bernama 'subskrip'). Saya pikir ini karena masalah yang diangkat di sini tapi saya tidak mengerti bagaimana membuat jawaban itu berfungsi dalam konteks ini. Setiap bantuan sangat dihargai.
Bryan Hanson
Saya memperbarui jawaban untuk bekerja di Swift 1.0 sekarang. Karena atributOfFileSystemForPath mengembalikan [NSObject: AnyObject]? Anda perlu menggunakan NSDictionary? karena bisa nihil dan kemudian membuka kamus untuk berlangganan. (Itu agak tidak aman, jadi saya akan memperbarui jawabannya sedikit belakangan dengan solusi yang lebih aman ketika saya punya waktu.)
RubenSandwich
Terima kasih atas pembaruannya. Ternyata, sekitar satu jam sebelum balasan Anda, saya telah melanjutkan dan merumuskan masalah ini sebagai pertanyaan baru di sini . Ada jawaban di sana sekarang, tetapi karena metode berurusan dengan opsional ini agak buram bagi saya, saya ingin melihat pendekatan lain pada kenyamanan Anda. Sampaikan salamku untuk adikmu Rachel.
Bryan Hanson
Bryan, saya akan menyarankan jawaban pertama untuk pertanyaan Anda yang dijawab karena merupakan campuran yang baik antara keamanan dan kejelasan. Saya tidak yakin bisa memberikan jawaban yang lebih baik daripada itu. Opsional dapat menjadi membingungkan pada awalnya, saya sangat menyarankan membaca bagian manual Swift pada opsional itu cukup baik.
RubenSandwich
Sangat dihargai, saya akan melihat manual itu lagi dan saya telah menemukan beberapa pertanyaan SO yang bagus juga. Bryan
Bryan Hanson
9

Inilah jawaban saya dan mengapa lebih baik.

Jawab (Cepat):

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
}

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

Mengapa lebih baik:

  • Memanfaatkan perpustakaan bawaan Cocoa NSByteCountFormatter , yang berarti tidak ada perhitungan manual yang gila dari byte ke gigabytes. Apple melakukan ini untuk Anda!
  • Mudah diterjemahkan: NSByteCountFormatterapakah ini untuk Anda. Misalnya. Ketika bahasa perangkat diatur ke Bahasa Inggris, string akan membaca 248,8 MB tetapi akan membaca 248,8 Mo ketika diatur ke Prancis, dan lain-lain untuk bahasa lain.
  • Nilai default diberikan jika terjadi kesalahan.
ChrisJF
sumber
1
@JuanBoero Diposting di Swift 3.1 (akhirnya)!
ChrisJF
7

Klarifikasi penting (setidaknya untuk saya). Jika saya menghubungkan iPod saya ke Mac saya, ini adalah info yang diperlihatkan oleh iTunes App.

Informasi memori iPod dari aplikasi iTunes

Ketika saya menggunakan kode di atas:

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 menunjukkan kepada saya: 17,41 GB

CountStyle NSByteCountFormatterCountStyleBinary menunjukkan kepada saya: 16,22 GB

16,22 GB ( NSByteCountFormatterCountStyleBinary ) Ini adalah persis jumlah yang ditunjukkan App iTunes kepada saya ketika saya menghubungkan iPod saya ke Mac saya.

Markus
sumber
mungkin File hanya untuk file MAC dan bukan iOS?
João Nunes
jumlah byte yang sama dikalikan 1000 (KB lalu MB lalu GB) dibandingkan 1024.
Jim75
7

Perbarui dengan API akurat baru untuk mendapatkan ukuran yang tersedia pada disk yang tersedia di iOS11. Berikut adalah deskripsi untuk kunci sumber daya API baru:

#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

Saya silang membandingkan hasil dari kunci " FileAttributeKey.systemFreeSize " dan kunci " URLResourceKey.volumeAvailableCapacityForImportantUsageKey " dan menemukan hasil yang dikembalikan dari " volumeAvailableCapacityForImportantUsageKey " persis sama dengan penyimpanan yang tersedia yang ditampilkan di UI. Bandingkan ruang disk kosong yang tersedia Berikut ini adalah implementasi cepat:

class var freeDiskSpaceInBytesImportant:Int64 {
    get {
        do {
            return try URL(fileURLWithPath: NSHomeDirectory() as String).resourceValues(forKeys: [URLResourceKey.volumeAvailableCapacityForImportantUsageKey]).volumeAvailableCapacityForImportantUsage!
        } catch {
            return 0
        }
    }
}
Evilisn Jiang
sumber
Dari mana "penggunaan oportunistik" berasal dari tangkapan layar Anda?
rshev
Menemukannya volumeAvailableCapacityForOpportunisticUsageKey,.
rshev
Ya rshev, volumeTersediaKapasitasUntukOpportunistikPenggunaanKey mendapat "" penggunaan oportunistik "pada tangkapan layar saya
Evilisn Jiang
untuk melihat ukuran penyimpanan yang tersedia, haruskah saya meminta NSHomeDirectory()atau NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true). Apakah ada perbedaan menggunakan keduanya?
Suryakant Sharma
7

Anda dapat menemukan solusi lain dengan menggunakan Swift 4 danextension yang memberi Anda opsi yang baik.

Ini UIDeviceekstensi.

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

}

Dan penggunaan sampel:

UIDevice.current.totalDiskSpaceInBytes()
UIDevice.current.totalDiskSpace()
UIDevice.current.freeDiskSpaceInBytes()
UIDevice.current.freeDiskSpace()
UIDevice.current.usedDiskSpaceInBytes()
UIDevice.current.usedDiskSpace()
abdullahselek
sumber
Jangan gunakan !bukan menempatkan guardaman typecastingatau nilperiksa.
TheTiger
Terima kasih atas komentar Anda @TheTiger.
abdullahselek
3

Untuk iOS> = 6.0 Anda dapat menggunakan yang baru NSByteCountFormatter. Kode ini mendapatkan jumlah byte gratis yang tersisa sebagai string yang diformat.

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

Kode berikut adalah implementasi versi Swift 3.0 dari jawaban yang sebelumnya disediakan oleh 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
sumber
Mengapa mengembalikan lebih dari informasi ruang disk iPhone yang tersedia. Ketika menu pengaturan iPhone mengatakan 998MB, itu mengembalikan 1,2 GB
Harapan
1

untuk Swift sebagai ekstensi 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
        }
    }
}

Cara Penggunaan:

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

Output akan menjadi:

Memory 9656 of 207694 Mb available.
ale_stro
sumber
1

Saya tahu posting ini agak lama, tetapi saya pikir jawaban ini dapat membantu seseorang. Jika Anda ingin mengetahui ruang disk yang digunakan / bebas / total pada perangkat Anda dapat menggunakan Luminous . Itu ditulis dalam bahasa Swift. Anda hanya perlu menelepon:

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

atau

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

Implementasi cepat kode di atas: -

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


}

Sebut saja dari kelas lain.

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

Saat menguji nilai yang dikembalikan, itu sama seperti yang ditunjukkan oleh aplikasi lain. Setidaknya di iPhone 6S + saya. Hanya saja implementasi cepat dari jawaban yang ditunjukkan di atas. Dan bagi saya jawaban yang diterima tidak berhasil.

Bikram
sumber
0

ChrisJF menjawab dalam versi 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
sumber
0

Ekstensi Swift 5 untuk FileManagerpenanganan error yang tepat dan tanpa konversi string otomatis (konversi jumlah byte ke string sesuai keinginan Anda). Juga mengikuti FileManagerpenamaan.

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

Contoh penggunaan:

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
sumber