Best Practices

데이터 저장: plist

DesignThinker 2021. 10. 31. 15:53

개요

앱 샌드박스의 도큐먼트 폴더에 plist 파일에 사용자 데이터를 저장하는 방법에 대하여

 

프로세스

  1. 저장할 데이터 타입에 Codable 프로토콜 선언
  2. 데이터를 저장할 폴더 URL 오브젝트와 생성할 파일의 URL 오브젝트 준비
  3. 데이터 저장 메소드 구현
    1. 저장할 데이터 인코딩
    2. 인코드한 데이터를 앞서 생성한 파일 URL에 쓰기
    3. 저장을 실행할 위치에 저장 함수 구현
  4. 데이터 불러오기 메소드 구현
    1. plist파일 오브젝트 생성 (첫 실행시 없는 파일이므로 if let, try?)
    2. 앞서 생성한 오브젝트 디코딩
    3. 변수에 디코딩한 데이터 넣기
    4. 불러오기를 실행할 위치에 불러오기 함수 구현

 

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