Làm cách nào để phát hiện tổng dung lượng đĩa trống / trống trên thiết bị iPhone / iPad?


147

Tôi đang tìm kiếm một cách tốt hơn để phát hiện dung lượng đĩa trống / trống trên thiết bị iPhone / iPad theo lập trình.
Hiện tại tôi đang sử dụng NSFileManager để phát hiện dung lượng đĩa. Sau đây là đoạn mã thực hiện công việc cho tôi:

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


Tôi có đúng với đoạn trích trên không? hoặc có cách nào tốt hơn để biết tổng dung lượng đĩa trống / trống.
Tôi đã phát hiện tổng dung lượng đĩa trống, vì chúng tôi đã ngăn ứng dụng của chúng tôi thực hiện đồng bộ hóa trong kịch bản không gian đĩa thấp.


Tôi hy vọng liên kết stackoverflow sẽ giúp bạn ..
senthilMuthu

1
Có vẻ như mã anh ấy sử dụng trong câu hỏi của anh ấy tốt hơn mã trong liên kết bạn đã đưa ra (anh ấy chỉ kiểm tra một thư mục thay vì duyệt qua tất cả các thư mục con trong "/")
Kendall Helmstetter Gelner

Cảm ơn Mikhail cho liên kết. Nhưng tôi đang tìm kiếm tổng dung lượng đĩa trống / trống trên thiết bị iPhone / iPad, không chỉ là một thư mục cụ thể. Ví dụ: trên iPhone 32 GB, nếu tổng kích thước khả dụng / miễn phí là 28 GB, tôi sẽ có thể phát hiện ra điều đó theo lập trình.
Code.War Warrior

Tôi hy vọng liên kết này sẽ giúp: jayprakashdubey.blogspot.in/2014/07/ trên
Jayprakash Dubey

Câu trả lời:


152

CẬP NHẬT : Vì đã có rất nhiều thời gian trôi qua sau câu trả lời này và các phương thức / API mới đã được thêm vào, vui lòng kiểm tra các câu trả lời được cập nhật bên dưới cho Swift, v.v. Vì tôi không sử dụng chúng cho mình, tôi không thể bảo đảm cho họ.

Câu trả lời gốc : Tôi tìm thấy giải pháp sau đây làm việc cho tôi:

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

Nó trả về cho tôi chính xác kích thước mà iTunes hiển thị khi thiết bị được kết nối với máy.


4
Chuyển đổi sang float có thể cho kết quả không chính xác trên khoảng 2GB. Nếu bạn cần xử lý kích thước tệp thực sự lớn, thay vào đó hãy sử dụng gấp đôi hoặc dài gấp đôi.
Tro

Như được chỉ ra bởi Ash, phương pháp này có kết quả không chính xác. Trong iPad 2 của tôi, với 64 GB, nó bị lỗi +0,25 GB ... Phương pháp bên dưới, được đăng bởi David H, có kết quả chính xác khi sử dụng vars uint64_t.
Leandro Alves

3
Đoạn mã đã được chỉnh sửa để phản ánh các đề xuất từ ​​@David H như được hiển thị bên dưới.
Code.War Warrior

4
+200 MB không phải là vấn đề. Trong Cài đặt, tôi có "0 byte" dung lượng trống. Và khi tôi nhập và sử dụng ứng dụng của mình, phương pháp này báo cáo khoảng 150mb dung lượng trống. Sau đó, tôi lấp đầy không gian còn lại này và chỉ sau đó ứng dụng gặp sự cố. Vì vậy, tôi sẽ nói rằng phương pháp này cung cấp cho bạn nhiều thông tin chính xác hơn những gì bạn thấy trong Cài đặt.
ancajic

4
Tại sao không ai sử dụng NSUIntegerthay vì những thứ như uint64_t? Chúng tôi đang viết Obj-C, không phải C ++ hay C. NSUInteger sẽ cung cấp cho bạn số nguyên 64 bit không dấu, nhưng nếu mọi thứ thay đổi, tôi tưởng tượng rằng Apple sẽ cập nhật Macro đó (giả sử 128 bit tại một số điểm, trở thành hiện thực)
Goles

59

Sửa đổi nguồn bằng cách sử dụng dài không dấu:

- (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: có vẻ như ai đó đã chỉnh sửa mã này để sử dụng 'uint64_t' thay vì 'unsign long long'. Mặc dù trong tương lai gần, điều này sẽ tốt, nhưng chúng không giống nhau. 'uint64_t' là 64 bit và sẽ luôn như vậy. Trong 10 năm, "unsign long long" có thể là 128. đó là một điểm nhỏ nhưng tại sao tôi lại sử dụng unsignLongLong.


Tôi không có kinh nghiệm với hệ thống đếm tự động mới nhưng __autorelease dùng để làm gì? Thông thường bạn không cần phải tự động trả lại NSError đã trả lại
Reverend

Điều này có thể giúp: stackoverflow.com/questions/8862023/
Kẻ

3
trên iPod Touch 4th Gen của tôi chạy iOS 5.1, NSFileSystemFreeSize vẫn báo cáo quá 200 MB. Tôi in ra nội dung của toàn bộ NSDipedia trong trình gỡ lỗi ... NSFileSystemSize là chính xác mặc dù ... có ai có giải pháp cho vấn đề này không?
Zennichimaro

@Zennichimaro: Bạn đã khắc phục vấn đề của mình chưa? Tôi cũng đang đối mặt với vấn đề tương tự, nhận thêm 0,2 GB khi tôi kiểm tra dung lượng trống trong iPad. iPad đang hiển thị dung lượng trống 24,1 GB nhưng trong mã, nó đang hiển thị 24,3 GB.
Sudheer Kumar Palchuri

1
@Diejmon bạn không thể yêu cầu NSNumber cho kích thước tích hợp của loại này. Đây là lý do tại sao đối với những thứ như vậy tôi thích một đơn vị kích thước bit đã biết. Mặc dù về mặt kỹ thuật tôi đồng ý với tuyên bố của bạn, tôi đã có đủ cảnh báo để xử lý việc sử dụng NSInteger và định dạng chuỗi! 64 bit sẽ là đủ bit cho chắc chắn trong đời tôi và của bạn.
David H

34

Tôi đã viết một lớp để có bộ nhớ khả dụng / sử dụng bằng Swift. Bản demo tại: https://github.com/thanhcuong1990/swift-disk-status
Swift 4 được cập nhật.

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

}

Bản giới thiệu

lấy trạng thái không gian đĩa với Swift


Bạn có biết tại sao MBFormatter lại ở đó không? Nó không được sử dụng ở bất cứ đâu.
Ben Sinclair

MBFormatter là một hàm để chuyển đổi bất kỳ giá trị nào thành giá trị MB. Tôi không sử dụng nó cho dự án demo. Nhưng tôi cần cho dự án khác.
Cường Lâm

1
Điều này là tuyệt vời để đặt trong một phần mở rộng FileManager.
Leon

2
iTunes hiển thị 18,99 GB miễn phí nhưng tôi nhận được 13,41 GB khi tôi sử dụng các phương pháp được mô tả. Có ai biết tôi nhớ gì không?
Vitalii Boiarskyi

1
@CuongLam Lỗi unwrapping không bị ném và không bị bắt bởi do / Catch. Mã nguồn mẫu phải được viết để xử lý lỗi chính xác. stackoverflow.com/questions/34628999/iêu
SafeFastExpressive 26/11/18

26

Nếu bạn cần chuỗi được định dạng với kích thước, bạn có thể xem thư viện đẹp trên 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
Để định dạng, người ta cũng có thể sử dụng NSBytCounterFormatter
Daniel Barden

Điều này vẫn có xu hướng lỗi tương tự + 200 MB: stackoverflow.com/questions/9270027/ trên
Paulius Liekis

13

Không sử dụng 'không dấu', nó chỉ có 32 bit sẽ vượt quá 4GB, ít hơn dung lượng trống của iPad / iPhone thông thường. Sử dụng dài không dấu (hoặc uint64_t) và truy xuất giá trị ra khỏi NSNumber dưới dạng int 64 bit bằng cách sử dụng unsignLongLongValue.


3
Nó tốt hơn một mẹo - "Đó là luật" :-) Như ông nói, mã ban đầu hoàn toàn sai.
David H

13

Nếu bạn muốn lấy không gian trống còn lại bằng Swift thì hơi khác một chút. Bạn cần sử dụng các thuộc tínhOfFileSystemForPath () thay vì các thuộc tínhOfItemAtPath ():

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: Cập nhật cho Swift 1.0
Chỉnh sửa 2: Cập nhật cho sự an toàn, sử dụng câu trả lời Martin R .
Chỉnh sửa 3: Cập nhật cho Swift 2.0 (bởi dgellow )


Tôi đã cố gắng sử dụng câu trả lời này, nhưng nó sẽ không được biên dịch theo GM ([NSObject: AnyObject]? Không có thành viên có tên 'đăng ký'). Tôi nghĩ rằng đây là do vấn đề được nêu ra ở đây nhưng tôi không hiểu làm thế nào để câu trả lời đó hoạt động trong bối cảnh này. Bất kỳ trợ giúp đánh giá rất cao.
Bryan Hanson

Tôi đã cập nhật câu trả lời để hoạt động trên Swift 1.0 ngay bây giờ. Bởi vì các thuộc tínhOfFileSystemForPath trả về [NSObject: AnyObject]? bạn cần truyền tới NSDipedia? vì nó có thể là con số không và sau đó mở ra từ điển để đăng ký nó. (Đó là một chút không an toàn, vì vậy tôi sẽ cập nhật câu trả lời sau một chút với giải pháp an toàn hơn khi tôi có thời gian.)
RubenSandwich

Cảm ơn các cập nhật. Hóa ra, khoảng một giờ trước khi trả lời của bạn, tôi đã đi trước và đặt vấn đề là một câu hỏi mới ở đây . Hiện tại đã có câu trả lời, nhưng vì phương pháp xử lý các tùy chọn này hơi mờ đối với tôi, tôi rất muốn thấy một cách tiếp cận khác một cách thuận tiện. Gửi lời chào của tôi đến em gái của bạn Rachel.
Bryan Hanson

Bryan, tôi sẽ đề nghị câu trả lời đầu tiên cho câu hỏi đã trả lời của bạn vì đây là một kết hợp tốt của sự an toàn và rõ ràng. Tôi không chắc là tôi có thể đưa ra một câu trả lời tốt hơn sau đó. Tùy chọn ban đầu có thể gây nhầm lẫn, tôi thực sự khuyên bạn nên đọc phần hướng dẫn sử dụng Swift trên các tùy chọn, nó khá tốt.
RubenSandwich

Rất cảm kích, tôi sẽ xem lại hướng dẫn đó và tôi cũng đã tìm thấy một số câu hỏi SO hay. Bryan
Bryan Hanson

9

Đây là câu trả lời của tôi và tại sao nó tốt hơn.

Trả lời (Swift):

func remainingDiskSpaceOnThisDevice() -> String {
    var remainingSpace = NSLocalizedString("Unknown", comment: "The remaining free disk space on this device is unknown.")
    if let attributes = try? FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory()),
        let freeSpaceSize = attributes[FileAttributeKey.systemFreeSize] as? Int64 {
        remainingSpace = ByteCountFormatter.string(fromByteCount: freeSpaceSize, countStyle: .file)
    }
    return remainingSpace
}

Trả lời (Mục tiêu-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;
}

Tại sao nó tốt hơn:

  • Sử dụng thư viện được xây dựng trong thư viện NSByteCountFormatter , nghĩa là không có phép tính thủ công điên rồ nào từ byte đến gigabyte. Apple làm điều này cho bạn!
  • Dễ dàng dịch: NSByteCountFormatterlàm điều này cho bạn. Ví dụ: Khi ngôn ngữ của thiết bị được đặt thành tiếng Anh, chuỗi sẽ đọc 248,8 MB nhưng sẽ đọc 248,8 Mo khi được đặt thành tiếng Pháp, et cetera cho các ngôn ngữ khác.
  • Một giá trị mặc định được đưa ra trong trường hợp có lỗi.

1
@JuanBoero Đăng trong Swift 3.1 (cuối cùng)!
ChrisJF

7

Làm rõ quan trọng (ít nhất là đối với tôi). Nếu tôi kết nối iPod với máy Mac thì đây là thông tin được hiển thị bởi iTunes App.

Thông tin bộ nhớ iPod từ ứng dụng iTunes

Khi tôi sử dụng đoạn mã trên:

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

Số đếm NSByteCountFormatterCountStyleFile cho tôi thấy: 17,41 GB

Số đếm NSByteCountFormatterCountStyleBinary cho tôi thấy: 16,22 GB

16,22 GB ( NSByteCountFormatterCountStyleBinary ) Đây chính xác là con số mà Ứng dụng iTunes hiển thị cho tôi khi tôi kết nối iPod với máy Mac.


Có lẽ File chỉ dành cho các tệp MAC chứ không phải iOS?
João Nunes

đó là cùng một lượng byte nhân với 1000 (KB rồi MB rồi GB) so với 1024.
Jim75

7

Cập nhật với API chính xác mới để có kích thước khả dụng trên đĩa có sẵn trong iOS11. Dưới đây là mô tả về khóa tài nguyên API mới:

#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

Tôi đã so sánh các kết quả từ khóa " FileAttributionKey.systemFreeSize " và khóa " URLResourceKey.volumeAv AvailableCapacityForImportantUsageKey " và tìm thấy kết quả trả về dạng " volumeAv AvailableCapacityForImportantUsageKey " khớp chính xác với lưu trữ có sẵn trên UI. Có sẵn dung lượng đĩa trống Đây là cách thực hiện nhanh chóng:

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

Trường hợp sử dụng cơ hội của vùng nào mà Cameron đến từ ảnh chụp màn hình của bạn?
rshev

Tìm thấy nó , volumeAvailableCapacityForOpportunisticUsageKey.
rshev

Có rshev, volumeAv AvailableCapacityForOpportunisticUsageKey được "sử dụng cơ hội" trên màn hình của tôi
Evilisn Jiang

để xem kích thước lưu trữ có sẵn, tôi nên truy vấn bằng NSHomeDirectory()hoặc NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true). Có sự khác biệt nào khi sử dụng hai cái này không?
Suryakant Sharma

7

Bạn có thể tìm một giải pháp khác bằng cách sử dụng Swift 4extensioncung cấp cho bạn một lựa chọn tốt.

Đây là UIDevicephần mở rộng.

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

}

Và sử dụng mẫu:

UIDevice.current.totalDiskSpaceInBytes()
UIDevice.current.totalDiskSpace()
UIDevice.current.freeDiskSpaceInBytes()
UIDevice.current.freeDiskSpace()
UIDevice.current.usedDiskSpaceInBytes()
UIDevice.current.usedDiskSpace()

Không sử dụng !thay vào đó guardđể an toàn typecastinghoặc nilkiểm tra.
TheTiger

Cảm ơn ý kiến ​​của bạn @TheTiger.
abdullahselek

3

Đối với iOS> = 6.0, bạn có thể sử dụng mới NSByteCountFormatter. Mã này nhận được số byte miễn phí còn lại dưới dạng một chuỗi được định dạng.

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

Mã sau đây là phiên bản Swift 3.0 thực hiện câu trả lời được cung cấp trước đây bởi 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

}

Tại sao điều đó trở lại nhiều hơn thông tin không gian đĩa có sẵn của iPhone. Khi menu cài đặt của iPhone cho biết 998 MB, trả về 1,2 GB
Hy vọng

1

cho Swift dưới dạng tiện ích mở rộng 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
        }
    }
}

Cách sử dụng:

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

Đầu ra sẽ là:

Memory 9656 of 207694 Mb available.

1

Tôi biết bài đăng này hơi cũ, nhưng tôi nghĩ câu trả lời này có thể giúp được ai đó. Nếu bạn muốn biết không gian đĩa đã sử dụng / miễn phí / tổng số trên thiết bị, bạn có thể sử dụng dạ quang . Nó được viết bằng Swift. Bạn chỉ phải gọi:

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

hoặc là

Luminous.System.Disk.freeSpaceInBytes()
Luminous.System.Disk.usedSpaceInBytes()

1

Swift thực hiện mã trên: -

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


}

Gọi nó từ bất kỳ lớp nào khác.

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

Trong khi kiểm tra giá trị được trả về, nó giống như được hiển thị bởi các ứng dụng khác. Ít nhất là trong iPhone 6S + của tôi. Đó chỉ là việc thực hiện nhanh chóng của câu trả lời được hiển thị ở trên. Và đối với tôi, câu trả lời được chấp nhận đã không hoạt động.


0

Câu trả lời của ChrisJF trong phiên bản 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

Tiện ích mở rộng Swift 5 để FileManagerxử lý lỗi thích hợp và không có chuyển đổi chuỗi tự động (chuyển đổi số byte thành chuỗi theo ý bạn). Cũng theo FileManagercách đặt tên.

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

Ví dụ sử dụng:

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)")
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.