[iOS] 총 / 남은 기기 용량 알아내는 법
남은 기기 용량을 알아야 할 일이 생겨서 찾아봤더니..
func deviceRemainingFreeSpaceInBytes() -> Int64? {
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).last!
guard
let systemAttributes = try? FileManager.default.attributesOfFileSystem(forPath: documentDirectory),
let freeSize = systemAttributes[FileAttributeKey.systemFreeSize] as? NSNumber
else {
// something failed
return nil
}
return freeSize.int64Value
}
이런 코드를 심심치않게 볼 수 있었다.
여기서 중요한 부분은
let freeSize = systemAttributes[FileAttributeKey.systemFreeSize]
FileAttributeKey를 사용했다는 점! (물론 FileAttributeKey는 생략이 가능하다)
GPT도 위 FileAttributeKey.systemFreeSize 를 사용하여 알려줬다.
나 같은 경우에는 166.8 GB 라고 나와야하는데 위 코드로 실행해봤더니 33.97 GB로 나오는것이다.
let freeSize = systemAttributes[FileAttributeKey.systemFreeSize]
찾아보니 FileAttributeKey를 사용하는 것은 더이상 정확하지 않다고 한다.
# 남은 용량 계산하기
func getFreeDiskSpaceByte() -> Int64? {
let fileURL = URL(fileURLWithPath:"/")
let values = try? fileURL.resourceValues(forKeys: [URLResourceKey.volumeAvailableCapacityForImportantUsageKey])
return values?.volumeAvailableCapacityForImportantUsage
}
코드 출처 : https://developer.apple.com/documentation/foundation/urlresourcekey/checking_volume_storage_capacity
이렇게 해서 남은 용량을 바이트단위로 얻어올 수 있다.
그리고 GB, MB등으로 바꾸고 싶다면 ByteCountFormatter를 이용하여 포맷팅이 가능하다.
func getFreeDiskSpace(_ byteCount: Int64) -> String {
let formatter = ByteCountFormatter()
formatter.allowedUnits = .useGB
formatter.countStyle = .file
formatter.includesUnit = true
return formatter.string(fromByteCount: byteCount) // ex. "100 GB"
}
allowedUnits ➡️ 허용할 단위. 나는 GB만 허용했는데,
formatter.allowedUnits = [.useGB, .useKB]
이렇게 배열을 넘길수도 있어서, 자신이 허용할 단위들을 포함해주면된다. 전부 사용하는 useAll도 있으니 참고!
countStyle ➡️ 기본값은 file이다. (그래서 위 코드는 딱히 필요하진 않지만 설명을 위해..)
4가지 case를 가지고 있는데, file 또는 memory를 사용할것은 권장하고 있다.
file과 memory의 차이점을 간단하게 보자면 allowedUnits을 useKB로 지정해두고 100000000을 넣으면
- file : 100,000 KB
- memory : 97,656 KB
남은 용량은 file로 지정했을 때 더 정확하게 나왔다. (설정에 있는 남은 용량과 거의 똑같이 나옴)
includesUnit ➡️ "100 GB"말고 "100"처럼 뒤에 단위(unit)은 제거하고 숫자만 가져오고싶을수도 있는데,
이때 includesUnit을 false로 주면 된다. (기본값 true)
나는 이걸 모르고 정규식을 썼었는데.. 알고있으면 좋을 것 같아서 넣어봤다.
# 총 용량 계산하기
URLResourceKey에 volumeTotalCapacityKey가 있어서 요걸 사용하면 된다.
func getTotalDiskSpaceByte() -> Int? {
let fileURL = URL(fileURLWithPath:"/")
let values = try? fileURL.resourceValues(forKeys: [.volumeTotalCapacityKey])
return values?.volumeTotalCapacity
}
시뮬레이터로 했을 때는 완전히 동일하게 나왔으나
256GB 인 실기기로 테스트해봤을 때, 255.87GB 가 나왔다. 흠.. 내 생각보다 오차가 커서 놀랐다.
# URLResourceKey
URLResourceKey에는 volumeAvailableCapacityForImportantUsageKey / volumeTotalCapacityKey 를 포함하여 총 4가지가 존재한다.
1. volumeAvailableCapacityForImportantUsageKey
중요한 리소스를 저장하기 위해 볼륨에서 사용 가능한 용량(바이트)에 대한 key
사용자 요청 or 앱이 제대로 작동하는데 필요한 리소스 (ex. 사용자가 시청하려는 비디오 / 게임의 다음 레벨에 필요한 리소스)를 기반으로 데이터를 저장하려는 경우에는 이거 쓰면됨
2. volumeAvailableCapacityForOpportunisticUsageKey
중요하지 않은 리소스를 저장하기 위해 볼륨에서 사용 가능한 용량(바이트)에 대한 key
보다 예측적인(predictive) 방식으로 데이터를 다운로드 하는 경우(ex. 사용자가 최근에 시청한 TV시리즈의 새로운 에피소드를 다운로드 하려는 경우) 에는 이거 쓰면됨
볼륨의 사용 가능한 용량(바이트)에 대한 key
Q : 위에 #남은 용량 계산하기에서 volumeAvailableCapacityForImportantUsageKey 썼는데.. volumeAvailableCapacityKey이걸 써야하는거 아님..?
A : 나도 그런 줄 알았으나..시뮬레이터에서는 제대로 나오지만 실기기에서는 이상한 값이 나오는 현상이 있었다;;
테스트해보니 제일 위의 FileAttributeKey.systemFreeSize 를 썼을때와 동일한 값이 나왔다.
그래서 제대로 나오는 volumeAvailableCapacityForImportantUsageKey 를 믿고 씀. (실제로 시뮬/실기기 둘 다 제대로 나옴)
볼륨의 총 용량(바이트)에 대한 key