[SwiftUI] Document File Order

looloolalaa·2022년 8월 24일
0

Problem

FileManager 를 이용하여 기기 내부(document folder)에 파일들을 생성할 때 순서가 없이 저장된다. 즉 file0, file1, file2 를 순차적으로 생성하여도, 정작 url 들을 읽으면 file2, file0, file1 과 같이 생성 순서가 지켜지지 않는다. 이는 에러가 아니라 Swift 의 정상 동작이다.

물론 순서가 중요하지 않은 앱이라면 큰 문제가 되지 않지만 순서가 중요하다면 문제가 될 수 있다.

파일을 생성한 순서대로 읽혀지기를 원했다. 그래서 write 대신 append 메소드가 없을까 찾아보기도 하고 read 할 때 생성 순서대로 읽는 option 이 없을까도 찾아 봤지만 없었다. 결국 그 답을 creationDate 에서 찾았다.

Code

문제 상황을 연출하는 테스트 코드를 만들어 보았다. 핵심을 이해하기 위함이므로 전체 코드는 쓰지 않았다.

우선 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 가 출력되는 것이다.

Solution

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 를 확인할 수 있다.

Done

  • FileAttributeKey 에는 creationDate 말고도 modificationDate 라는 타입 프로퍼티도 존재한다. 따라서 생성 날짜가 아니라 최근 수정 날짜로도 정렬을 할 수 있다.

Reference

profile
실패도 배우는 게 있으면 성공이다.

0개의 댓글