개요
앱 샌드박스의 도큐먼트 폴더에 plist 파일에 사용자 데이터를 저장하는 방법에 대하여
프로세스
- 저장할 데이터 타입에 Codable 프로토콜 선언
- 데이터를 저장할 폴더 URL 오브젝트와 생성할 파일의 URL 오브젝트 준비
- 데이터 저장 메소드 구현
- 저장할 데이터 인코딩
- 인코드한 데이터를 앞서 생성한 파일 URL에 쓰기
- 저장을 실행할 위치에 저장 함수 구현
- 데이터 불러오기 메소드 구현
- plist파일 오브젝트 생성 (첫 실행시 없는 파일이므로 if let, try?)
- 앞서 생성한 오브젝트 디코딩
- 변수에 디코딩한 데이터 넣기
- 불러오기를 실행할 위치에 불러오기 함수 구현
Codable Protocol 선언
PropertyListEncoder가 인코드하는 어떤 오브젝트든지 반드시 Codable 프로토콜을 따라야만 한다.
class ChecklistItem: NSObject, Codable {
var text = ""
var checked = false
}
어떤 오브젝트가 어떤 프로토콜을 따른다고하면 으레 적용해야할 메소드들이 있지만, Codable 프로토콜을 적용할 오브젝트가 가진 프로퍼티들이 모두 스위프트의 스탠다드 타입들이라면, 스위프트가 이 타입들을 어떻게 encode/decode해야하는지 알고 있기 때문에 별도로 메소드를 작성할 게 없다. 이것을 default implementation이라고 표현함.
도큐먼트 폴더 경로 가져오기
func documentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
retun paths[0]
// return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
// return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
}
도큐먼트 폴더에 쓸 plist파일 경로 가져오기
func dataFilePath() -> URL {
return documentsDirectory().appendingPathComponent("Checklist").appendingPathExtension("plist")
// return documentsDirectory().appendingPathComponent("Checklist.plist")
}
데이터 저장하기
위에서 설정한 경로와 파일path에 데이터를 저장한다. 2가지 방법이 있다
do-catch Syntax 사용하기
func saveChecklistItems() {
let encoder = PropertyListEncoder()
do {
let encodedData = try encoder.encode(items)
try encodedData.write(to: dataFilePath(), option: Data.WritingOptions.atomic)
} catch {
print("Error encoding item array: \(error.localizedDescription)")
}
}
do{...} 블럭에서 error가 thrown 된 경우 catch 구문 안에서는 선언한적 없는 error 로컬 변수를 사용할 수 있다.
데이터 전달 또는 throwing error
encode 메소드와 write 메소드가 error를 throw 할 수 있는데, 이 때문에 try 키워드를 사용한다고 생각하자.
try? Keyword 사용하기
let propertyListEncoder = PropertyListEncoder()
let encodedData = try? propertyListEncoder.encode(data) //data: 인코드할 데이터
try? encodedData?.write(to: archiveURL, options: .noFileProtection)
데이터 전달 또는 nil 반환
try?키워드를 사용하면 encode, write 메소드가 error를 throwing하지 않고 optional Data를 리턴한다.
데이터 불러오기
do-catch Syntax를 사용해도 무방함. 여기서는 try? Keyword로 구현.
func loadChecklistItems() {
//1
let path = dataFilePath()
//2
if let data = try? Data(contentsOf: path) {
//3
let decoder = PropertyListDecoder()
do {
//4
items = try decoder.decode([ChecklistItem].self, from: data)
} catch {
print("Error decoding item array: \(error.localizedDescription)")
}
}
}
//2
path 경로에 있는 plist파일을 data 오브젝트로 불러옴.
data 오브젝트 불러오기가 실패하면 try? 키워드가 nil값을 리턴함
**앱을 깔고 처음 실행하는 경우라면 plist 파일이 없을 것**
//4
디코더가 디코딩할 데이터가 어떤 타입이 되야할지 첫번째 파라미터로 먼저 전달해야 함
디코딩한 결과를 var items = [ChecklistItem]() 변수에 넣어줌
이제 데이터를 저장하고 불러올 장소에 위에서 선언한 함수들을 실행하면 된다.
'Best Practices' 카테고리의 다른 글
alert 팝업 만들기 (0) | 2021.11.13 |
---|---|
Sandbox의 Documents 폴더 접근하기 (0) | 2021.10.31 |