วิธีการตรวจสอบพื้นที่ดิสก์ทั้งหมดที่มี / ว่างบนอุปกรณ์ 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จะช่วยคุณ ..
senthilMuthu

1
ดูเหมือนว่ารหัสที่เขาใช้ในคำถามของเขานั้นดีกว่ารหัสในลิงก์ที่คุณให้ (เขาแค่ตรวจสอบไดเรกทอรีเดียวแทนที่จะสำรวจไดเรกทอรีย่อยทั้งหมดภายใต้ "/")
Kendall Helmstetter Gelner

ขอบคุณ Mikhail สำหรับลิงค์ แต่ฉันกำลังมองหาพื้นที่ว่างบนดิสก์ทั้งหมดที่มี / ว่างบน iPhone / iPad ไม่ใช่แค่โฟลเดอร์เฉพาะ ตัวอย่างเช่นบน iPhone 32GB หากขนาดโดยรวม / ฟรีเป็น 28GB ฉันควรจะสามารถตรวจจับได้โดยทางโปรแกรม
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
การแปลงเป็นแบบลอยอาจให้ผลลัพธ์ที่ไม่ถูกต้องด้านบนประมาณ 2GB หากคุณต้องการจัดการกับไฟล์ขนาดใหญ่จริงๆให้ใช้ double หรือ long double แทน
Ash

วิธีนี้มีผลที่ไม่แม่นยำตามที่ Ash ชี้ให้เห็น ใน iPad 2 ของฉันที่มี 64GB นั้นล้มเหลวโดย +0.25 GB ... วิธีการด้านล่างโพสต์โดย David H มีผลลัพธ์ที่ถูกต้องเมื่อใช้ vint uint64_t
ลีอันโดรอัลเวส

3
มีการแก้ไขข้อมูลโค้ดเพื่อสะท้อนถึงคำแนะนำจาก @David H ดังที่แสดงด้านล่าง
Code.Warrior

4
+200 MB ไม่ใช่ปัญหา ในการตั้งค่าฉันมีที่ว่าง "0 ไบต์" และเมื่อฉันเข้าและใช้แอพของฉันวิธีการนี้จะรายงานพื้นที่ว่างประมาณ 150mb จากนั้นฉันเติมช่องว่างที่เหลืออยู่นี้จากนั้นแอปจึงขัดข้อง ดังนั้นฉันจะบอกว่าวิธีนี้ให้ข้อมูลที่ถูกต้องมากกว่าที่คุณเห็นในการตั้งค่า
ต้น

4
ทำไมไม่มีใครใช้NSUIntegerแทนสิ่งที่ชอบuint64_t? เรากำลังเขียน Obj-C ไม่ใช่ C ++ หรือ C NSUInteger จะให้จำนวนเต็ม 64 บิตที่ไม่ได้ลงนามตอนนี้ แต่ถ้าสิ่งต่าง ๆ เกิดขึ้นเปลี่ยนฉันคิดว่า Apple จะอัปเดตมาโครนั้น (สมมติว่า 128 บิตในบางจุดกลายเป็นของจริง)
Goles

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

แก้ไข: ดูเหมือนว่ามีคนแก้ไขรหัสนี้เพื่อใช้ 'uint64_t' แทน 'ยาวไม่ได้ลงนาม' ในขณะที่ในอนาคตอันใกล้นี้ควรจะดี แต่พวกเขาไม่เหมือนกัน 'uint64_t' คือ 64 บิตและจะเป็นเช่นนั้นเสมอ ใน 10 ปี 'ความยาวที่ไม่ได้ลงชื่อ' อาจเป็น 128 จุดเล็ก ๆ แต่ทำไมฉันใช้ unsongedLongLong


ฉันไม่เคยมีประสบการณ์กับระบบการนับอัตโนมัติแบบใหม่ แต่การหาข้อมูลด้วยตนเองเป็นแบบใด ปกติแล้วคุณไม่จำเป็นต้องยกเลิกการใช้ NSError ที่ส่งคืนโดยอัตโนมัติ
สาธุคุณ

สิ่งนี้อาจช่วยได้: stackoverflow.com/questions/8862023/…
Fabian Kreiser

3
บน iPod Touch 4th Gen ของฉันที่ใช้ iOS 5.1, NSFileSystemFreeSize ยังคงรายงานมากถึง 200 MBytes ฉันพิมพ์เนื้อหาของ NSDictionary ทั้งหมดในเครื่องมือดีบั๊ก ... NSFileSystemSize ถูกต้องแล้ว ... ใครมีวิธีแก้ปัญหานี้เหรอ?
Zennichimaro

@Zennichimaro: คุณแก้ไขปัญหาของคุณหรือไม่ ฉันกำลังเผชิญกับปัญหาเดียวกันรับ 0.2 GB พิเศษเมื่อฉันตรวจสอบพื้นที่ว่างใน iPad iPad แสดงพื้นที่ว่าง 24.1 GB แต่ในรหัสนั้นแสดง 24.3 GB
Sudheer Kumar Palchuri

1
@Diejmon คุณไม่สามารถถาม NSNumber สำหรับขนาดจำนวนเต็มของประเภทนี้ นี่คือเหตุผลสำหรับสิ่งต่าง ๆ ที่ฉันชอบหน่วยของขนาดบิตที่รู้จัก ในขณะที่ทางเทคนิคฉันเห็นด้วยกับข้อความของคุณฉันมีคำเตือนเพียงพอที่จะจัดการกับการใช้ NSInteger และสตริงรูปแบบ! 64 บิตจะเป็นบิตที่เพียงพอสำหรับอายุการใช้งานของฉันและของคุณ
David H

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 ฉันไม่ได้ใช้มันสำหรับโครงการตัวอย่าง แต่ฉันต้องการโครงการอื่น
Cuong Lam

1
นี่เป็นการดีที่จะใส่ในส่วนขยายของ FileManager
Leon

2
iTunes แสดงฟรี 18.99 GB แต่ฉันได้รับ 13.41 GB เมื่อฉันใช้วิธีการที่อธิบายไว้ ไม่มีใครรู้ว่าสิ่งที่ฉันพลาด?
Vitalii Boiarskyi

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
Daniel Barden

สิ่งนี้ยังมีแนวโน้มที่จะมีข้อผิดพลาด + 200MB เดียวกัน: stackoverflow.com/questions/9270027/ …
Paulius Liekis

13

อย่าใช้ 'ไม่ได้ลงนาม' มันเป็นเพียง 32 บิตซึ่งจะล้น 4GB ผ่านซึ่งน้อยกว่าพื้นที่ว่าง iPad / iPhone ทั่วไป ใช้ long long ที่ไม่ได้ลงชื่อ (หรือ uint64_t) และดึงค่าออกจาก NSNumber เป็น int 64- บิตเช่นกันโดยใช้ unsignedLongLongValue


3
มันดีกว่าคำแนะนำ - "มันเป็นกฎหมาย" :-) อย่างที่เขาพูดรหัสต้นฉบับมันผิดธรรมดา
David H

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

แก้ไข: อัปเดตสำหรับสวิฟท์ 1.0
แก้ไข 2: อัปเดตเพื่อความปลอดภัยโดยใช้คำตอบที่มาร์ตินอาร์เอส
แก้ไข 3: อัปเดตสำหรับ Swift 2.0 (โดยdgellow )


ฉันพยายามใช้คำตอบนี้ แต่จะไม่รวบรวมภายใต้ GM ([NSObject: AnyObject]? ไม่มีสมาชิกชื่อ 'subscript') ฉันคิดว่านี่เป็นปัญหาที่เกิดขึ้นที่นี่แต่ฉันไม่เข้าใจวิธีการทำให้คำตอบนั้นทำงานในบริบทนี้ ความช่วยเหลือใด ๆ ที่ชื่นชมอย่างมาก
ไบรอันแฮนสัน

ฉันได้อัปเดตคำตอบเพื่อใช้กับ Swift 1.0 แล้ว เนื่องจาก attributesOfFileSystemForPath ส่งกลับ [NSObject: AnyObject]? คุณจำเป็นต้องส่งไปที่ NSDictionary หรือไม่ เนื่องจากอาจเป็นศูนย์แล้วจึงแกะพจนานุกรมเพื่อห้อยลงมา (นั่นเป็นบิตที่ไม่ปลอดภัยดังนั้นฉันจะอัปเดตคำตอบเล็กน้อยด้วยโซลูชันที่ปลอดภัยยิ่งขึ้นเมื่อฉันมีเวลา)
RubenSandwich

ขอบคุณสำหรับการอัพเดท. ในฐานะที่เป็นมันจะเปิดออกประมาณหนึ่งชั่วโมงก่อนตอบกลับของคุณฉันได้ไปข้างหน้าและสูตรปัญหาเป็นคำถามสดที่นี่ มีคำตอบอยู่ที่นั่นในขณะนี้ แต่เนื่องจากวิธีการจัดการกับตัวเลือกนี้ค่อนข้างทึบแสงสำหรับฉันฉันชอบที่จะเห็นวิธีการอื่นตามที่คุณสะดวก ขอแสดงความนับถือ Rachel น้องสาวของฉัน
ไบรอันแฮนสัน

ไบรอันฉันขอแนะนำคำตอบแรกสำหรับคำถามที่คุณตอบเพราะเป็นส่วนผสมที่ดีและปลอดภัย ฉันไม่แน่ใจว่าฉันจะให้คำตอบที่ดีกว่านี้ได้ไหม ตัวเลือกอาจจะสับสนในตอนแรกฉันขอแนะนำอย่างยิ่งให้อ่านส่วนคู่มือ 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
}

คำตอบ (วัตถุประสงค์ -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;
}

ทำไมมันถึงดีกว่า:

  • ใช้ประโยชน์จากห้องสมุดในตัวของโกโก้ NSByteCountFormatterซึ่งไม่มีการคำนวณด้วยตนเองอย่างบ้าคลั่งจากไบต์ถึงกิกะไบต์ Apple ทำเพื่อคุณ!
  • แปลได้อย่างง่ายดาย: NSByteCountFormatterทำเพื่อคุณ เช่นเมื่อภาษาของอุปกรณ์ถูกตั้งค่าเป็นภาษาอังกฤษสตริงจะอ่าน 248.8 MB แต่จะอ่าน 248,8 Mo เมื่อตั้งเป็นภาษาฝรั่งเศสและอื่น ๆ สำหรับภาษาอื่น ๆ
  • ค่าเริ่มต้นจะได้รับในกรณีที่เกิดข้อผิดพลาด

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 GB

countStyle NSByteCountFormatterCountStyleBinaryแสดงให้ฉันเห็น: 16,22 GB

16,22 GB ( NSByteCountFormatterCountStyleBinary ) มันเป็นตรงหมายเลขที่ iTunes App แสดงให้ฉันเมื่อฉันเชื่อมต่อ iPod กับ Mac ของฉัน


อาจเป็นไฟล์สำหรับไฟล์ MAC เท่านั้นไม่ใช่ iOS?
João Nunes

มันคือจำนวนไบต์เดียวกันคูณด้วย 1,000 (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 " ตรงกับที่เก็บข้อมูลที่แสดงบน UI เปรียบเทียบพื้นที่ว่างในดิสก์ นี่คือการดำเนินการที่รวดเร็ว:

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

“ การใช้งานแบบฉวยโอกาส” มาจากไหนบนหน้าจอของคุณ
rshev

พบแล้ว, volumeAvailableCapacityForOpportunisticUsageKey.
rshev

ใช่ rshev, volumeAvailableCapacityForOpportunisticUsageKey ได้รับ "การใช้งานแบบฉวยโอกาส" บนหน้าจอของฉัน
Evilisn Jiang

เพื่อดูภาพขนาดการจัดเก็บข้อมูลที่มีอยู่ฉันควรสอบถามกับหรือNSHomeDirectory() NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)มีความแตกต่างในการใช้สองสิ่งนี้หรือไม่?
Suryakant Sharma

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 บอกว่า 998MB จะให้ผลตอบแทน 1.2 GB
หวังว่า

1

สำหรับSwiftเป็น UIDevice extension

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.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)")
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.