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;
}
上記のスニペットで修正しますか?または、利用可能な/空きディスク領域の合計を知るより良い方法があります。
ディスクの空き容量が少ないシナリオでアプリケーションが同期を実行できないようにするため、合計空きディスク容量を検出する必要があります。
UPDATE:この回答と新しいメソッド/ 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が表示するサイズを正確に返します。
符号なしlong longを使用してソースを修正:
- (uint64_t)freeDiskspace
{
uint64_t totalSpace = 0;
uint64_t totalFreeSpace = 0;
__autoreleasing NSError *error = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSDictionary *dictionary = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[paths lastObject] error: &error];
if (dictionary) {
NSNumber *fileSystemSizeInBytes = [dictionary objectForKey: NSFileSystemSize];
NSNumber *freeFileSystemSizeInBytes = [dictionary objectForKey:NSFileSystemFreeSize];
totalSpace = [fileSystemSizeInBytes unsignedLongLongValue];
totalFreeSpace = [freeFileSystemSizeInBytes unsignedLongLongValue];
NSLog(@"Memory Capacity of %llu MiB with %llu MiB Free memory available.", ((totalSpace/1024ll)/1024ll), ((totalFreeSpace/1024ll)/1024ll));
} else {
NSLog(@"Error Obtaining System Memory Info: Domain = %@, Code = %d", [error domain], [error code]);
}
return totalFreeSpace;
}
編集:誰かがこのコードを編集して、「unsigned long long」の代わりに「uint64_t」を使用するようです。近い将来、これは問題ないはずですが、同じではありません。 'uint64_t'は64ビットであり、常にそれです。 10年後の「unsigned long long」は128になります。これは小さなポイントですが、なぜunsignedLongLongを使用したのでしょうか。
サイズ付きのフォーマットされた文字列が必要な場合は、 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;
}
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
}
}
}
デモ
「符号なし」を使用しないでください。4GBを超えるとオーバーフローする32ビットのみで、iPad/iPhoneの一般的な空き容量よりも少なくなります。 unsigned long long(またはuint64_t)を使用し、unsignedLongLongValueを使用してNSNumberから64ビットintとして値を取得します。
Swiftを使用して残りの空き領域を取得する場合は、少し異なります。 attributesOfItemAtPath()の代わりにattributesOfFileSystemForPath()を使用する必要があります。
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用に更新
編集2:安全性のために更新 Martin Rの回答を使用 。
編集3:Swift 2.0用に更新(by dgellow )
ここに私の答えとそれが良い理由があります。
応答(スイフト):
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を読み取ります。重要な説明(少なくとも私にとって)。 iPodをMacに接続すると、これは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 show me:17,41 GB
CountStyle NSByteCountFormatterCountStyleBinary show me:16,22 GB
16,22 GB(NSByteCountFormatterCountStyleBinary)これは正確に iPodをMacに接続したときにiTunesアプリが表示する番号です。
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()
IOS11で利用可能なディスク上の利用可能なサイズを取得するために、新しい正確なAPIで更新します。新しい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に表示される使用可能なストレージと完全に一致することを確認しました。 Swiftの実装は次のとおりです。
class var freeDiskSpaceInBytesImportant:Int64 {
get {
do {
return try URL(fileURLWithPath: NSHomeDirectory() as String).resourceValues(forKeys: [URLResourceKey.volumeAvailableCapacityForImportantUsageKey]).volumeAvailableCapacityForImportantUsage!
} catch {
return 0
}
}
}
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];
次のコードは、ChrisJFが以前に提供した回答のSwift 3.0バージョンの実装です。
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
}
私はこの投稿が少し古いことを知っていますが、この答えは誰かを助けることができると思います。デバイスの使用済み/空き/合計ディスク容量を知りたい場合は、 Luminous を使用できます。 Swiftで書かれています。あなただけを呼び出す必要があります:
Luminous.System.Disk.freeSpace()
Luminous.System.Disk.usedSpace()
または
Luminous.System.Disk.freeSpaceInBytes()
Luminous.System.Disk.usedSpaceInBytes()
for Swift as 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.
上記のコードの迅速な実装:-
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 +では。上記の答えのSwift実装です。そして、私にとって受け入れられた答えはうまくいきませんでした。
時間を節約したい場合は、次のCocoaPodライブラリを使用してください。私はそれを使用しませんでしたが、それは動作するはずです。
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
}