Swift/etc

[Swift] UserDefaults 사용법 정리

devKen 2022. 9. 17. 22:33

참고 프로젝트 개요

- MVVM 구조

- SwiftUI

-ToDO 리스트 프로젝트

 

UserDefaults에 데이터 저장

// ViewModel.swift
class ListViewModel: ObservableObject {
@Published var items: [ItemModel] = [] {
	//ItemModel은 두개의 String과 하나의 Bool로 구성되어 있습니다.
        didSet {
       	  //items 값이 변화하면 감지하면 saveItem 메소드를 실행합니다.
            saveItem()
        }
    }
let itemsKey: String = "items_list"
    
func saveItem() {
        if let encodedData = try? JSONEncoder().encode(items) {
            UserDefaults.standard.set(encodedData, forKey: itemsKey)
        }
    }
}

saveItem이 UserDefaults를 사용하는 예시인데 Model을 그냥 다룰 수는 없기 때문에 데이터를 Json으로 다루고 저장합니다. 코드에서는 try와 JSONEncoder를 사용하여 items에 데이터가 존재하면 USerDefaults에 키 값으로 itemsKey에 데이터를 저장하도록 되어 있습니다.

여기서 forKey는 String이 들어가야 하며 오타 등으로 혼란이 발생하는 것을 방지하기 위해 itemsKey라는 변수를 생성하여 이용하였습니다.

UserDefaults에서 데이터 읽어오기

class ListViewModel: ObservableObject {
    @Published var items: [ItemModel] = [] {
        didSet {
            saveItem()
        }
    }
    let itemsKey: String = "items_list"
    
    init() {
        getItems()
    }
    
    func getItems() {
        guard
            let data = UserDefaults.standard.data(forKey: itemsKey),
            let savedItems = try? JSONDecoder().decode([ItemModel].self, from: data)
        else { return }
        self.items = savedItems
    }
}

init을 통해 getItems 메소드를 이용하여 데이터를 불러옵니다.

안에서는 UserDefaults.standard.data(forKey: )로 키에 해당하는 data를 가져올 수 있습니다. 가져온 data는 JsonDecoder를 통하여 ItemModel로 디코드 합니다. guard를 여러줄에 걸쳐 사용함으로써 줄마다 guard와 else return을 사용하는 걸 줄이는 기술을 볼 수 있습니다. 또한, items에 이렇게 불러워진 복사 합니다.

 

전체 코드

class ListViewModel: ObservableObject {
    @Published var items: [ItemModel] = [] {
        didSet {
            saveItem()
        }
    }
    let itemsKey: String = "items_list"
    
    init() {
        getItems()
    }
    
    func getItems() {
        guard
            let data = UserDefaults.standard.data(forKey: itemsKey),
            let savedItems = try? JSONDecoder().decode([ItemModel].self, from: data)
        else { return }
        self.items = savedItems
    }
    func deleteItem(indexSet: IndexSet) {
        items.remove(atOffsets: indexSet)
    }
    func moveItem(from: IndexSet, to: Int) {
        items.move(fromOffsets: from, toOffset: to)
    }
    func addItem(title: String) {
        let newItem = ItemModel(title: title, isCompleted: false)
        items.append(newItem)
    }
    func updateItem(item: ItemModel) {
        if let index = items.firstIndex(where: { $0.id == item.id}) {
            items[index] = item.updateCompletion()
        }
    }
    func saveItem() {
        if let encodedData = try? JSONEncoder().encode(items) {
            UserDefaults.standard.set(encodedData, forKey: itemsKey)
        }
    }
}