FileManager 를 이용하여 기기 내부(document folder)에 파일들을 생성할 때 순서가 없이 저장된다. 즉 file0, file1, file2 를 순차적으로 생성하여도, 정작 url 들을 읽으면 file2, file0, file1 과 같이 생성 순서가 지켜지지 않는다. 이는 에러가 아니라 Swift 의 정상 동작이다.
물론 순서가 중요하지 않은 앱이라면 큰 문제가 되지 않지만 순서가 중요하다면 문제가 될 수 있다.
파일을 생성한 순서대로 읽혀지기를 원했다. 그래서 write 대신 append 메소드가 없을까 찾아보기도 하고 read 할 때 생성 순서대로 읽는 option 이 없을까도 찾아 봤지만 없었다. 결국 그 답을 creationDate 에서 찾았다.
문제 상황을 연출하는 테스트 코드를 만들어 보았다. 핵심을 이해하기 위함이므로 전체 코드는 쓰지 않았다.
우선 document 에 "Text0" 라는 타이틀, "Text0" 라는 내용을 가진 파일을 write 버튼으로 쓰도록 하여 Text0 ~ Text2 까지 3개가 저장되어 있게 했다.
struct Temp {
var title: String
var content: String
}
//ContentView
@State private var temps: [Temp] = []
Button("read") {
let fileManager = FileManager()
let documentURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!
do {
let allTextFileURLs = try fileManager.contentsOfDirectory(at: documentURL, includingPropertiesForKeys: nil)
for url in allTextFileURLs {
let title = url.lastPathComponent
let content = try String(contentsOf: url, encoding: .utf8)
let newTemp = Temp(title: title, content: content)
temps.append(newTemp)
}
} catch {
print("Error Reading File: \(error.localizedDescription)")
}
}
그 다음 read 버튼을 눌러 document 에서부터 모든 파일 URL을 읽는다. url 로 title 과 content 를 읽어서 Temp 객체를 만들고 temps 에 차례로 저장한다.
이제 temps 출력을 해보면
순서가 뒤죽박죽인 것을 볼 수 있다.
우리가 원하는 것은 파일 생성 순서인 Text0 Text1 Text2 가 출력되는 것이다.
let attr = try fileManager.attributesOfItem(atPath: url.path)
let creationDate = attr[FileAttributeKey.creationDate] as! Date
file url 을 가지고 파일 생성 날짜인 creationDate 를 알아 낼 수 있다. Temp 구조체에 생성 날짜를 저장하는 프로퍼티를 추가하고 temps 를 이 프로퍼티로 정렬하는 것으로 순서를 유지한다. 결국 폴더 내부의 순서를 정렬하는 것이 아닌 우리가 직접 쓰는 곳에서 정렬하는 방식이다.
struct Temp {
var title: String
var content: String
var creationDate: Date //add
}
//modify
Button("read") {
let fileManager = FileManager()
let documentURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!
do {
let allTextFileURLs = try fileManager.contentsOfDirectory(at: documentURL, includingPropertiesForKeys: nil)
for url in allTextFileURLs {
let title = url.lastPathComponent
let content = try String(contentsOf: url, encoding: .utf8)
//creationDate
let attr = try fileManager.attributesOfItem(atPath: url.path)
let creationDate = attr[FileAttributeKey.creationDate] as! Date
let newTemp = Temp(title: title, content: content, creationDate: creationDate) //add
temps.append(newTemp)
}
} catch {
print("Error Reading File: \(error.localizedDescription)")
}
//sort
temps.sort { $0.creationDate < $1.creationDate }
}
이제 생성 날짜를 같이 출력해보면
만들어진 날짜와 그걸로 정렬이 된 temps 를 확인할 수 있다.