์๋ ํ์ธ์โจ
์ค๋์ ์ ๊ฐ ๋ง๋ Todo List Project๋ค์ ๋ฐ์ดํฐ๊ฐ ์ด๋ป๊ฒ ๊ตฌ์ฑ๋์ด ์๋์ง ๋ฏ์ด๋ณผ ๊ฒ์ ๋๋ค.
[ Project ] todoList ๊ตฌํํ๊ธฐ #2์์ ๊ตฌํํ ๋ฐ์ดํฐ๋ค์ CoreData๋ฅผ ์ ์ฉํ์์ด์!
CoreData๊ฐ ๋ฌด์์ธ์ง ๋ชจ๋ฅด๊ฒ ๋ค๋ฉด ๋งํฌ๋ฅผ ํ๊ณ ๊ฐ ๋ณด๊ณ ์ค์๋ฉด ๋ฉ๋๋ค.
CoreData ๋์ํ
ํ์ฌ ์ ๊ฐ ์์ฑํ TodoData๋ฅผ ๋์ํ ์ํจ ํ์ ๋๋ค. ์ ๋ง ๋ณผ์ ๊ฒ ์์ด ๊ทธ๋ ธ๋ค๋งใ ใ ..
๊ทธ๋ฆผ์ ์ค๋ฅธ์ชฝ ํ์ฒ๋ผ ์ ๊ฐ todoData๋ฅผ ์์ฑํ๋ฉด ์ ๋ฐ ํ๋ก ๋ฐ์ดํฐ๊ฐ ์ ์ฅ์ด ๋์ด์์ ๊ฑฐ์์! ๊ทธ๋ผ ์ด ๋ฐ์ดํฐ๋ค์ ์ดํ๋ก ๊ฐ์ง๊ณ ์์ ์ฌ์ฉํ๊ฑฐ๋ ์์ ํ๊ฑฐ๋ ์ญ์ ๋ฅผ ํด์ผํฉ๋๋ค. ๊ทธ ๋ฐฉ๋ฒ์ ์ง๊ธ๋ถํฐ ์์๋ด ์๋ค.
CoreData ์ฌ์ฉ๋ฐฉ๋ฒ
์ฐ์ CoreData๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ coredata ํ๋ ์์ํฌ๋ฅผ import๋ฅผ ํด์ฃผ์ด์ผ ํฉ๋๋ค.
import CoreData
๊ธฐ๋ณธ์ ์ผ๋ก ์ฑ์ ๋ง๋ค์ด์ ์ฝ๋ฉ์ ์งค๋๋ Data๋ฅผ ๊ด๋ฆฌํด์ฃผ๋ DataManager ๋ผ๋ ํด๋์ค๋ฅผ ์์ฑํ์ค๊ฑฐ์์!
CoreData๋ ์ด DataManager ํด๋์ค ๋ด์์ ๋ฐ์ดํฐ๋ฅผ ๊ด๋ฆฌํด์ค ๊ฒ์
๋๋ค.
์ ๋ Singleton ๋์์ธ ํจํด์ ๋ฐ๋ผ ์ฑ์ ๊ตฌํํ์์ด์! ์ฐธ๊ณ ํด์ฃผ์๊ธธ ๋ฐ๋๋๋คโจ. DataManager ํด๋์ค๋ฅผ ์์ฑํ๋ค๋ฉด ์ด ํด๋์ค์ ์ธ์คํด์ค๋ฅผ ๋ง๋ค์ด์ DataManager ํจ์๋ค์ ์ ๊ทผ์ ํด์ผ๊ฒ ์ฃ ?! ์ ๋ ์ฌ๊ธฐ์ Singleton ํจํด์ ๋ฐ๋ผ ๋ฑ ํ๋ฒ๋ง DataManager ํด๋์ค๋ฅผ ์ธ์คํด์คํํ์ฌ ์ฌ์ฉํ ๊ฒ์ ๋๋ค.
static let shared = ListDataManager()
์์ ์ฝ๋๋ static์ผ๋ก ์ ์ธ๋ shared ๋ผ๋ ๋ณ์์ DataManager์ ์ธ์คํด์ค๋ฅผ ์์ฑํ ๊ฒ์ ๋๋ค. ๊ทธ๋ผ ๋ฑ ํ๋ฒ๋ง ์ธ์คํด์คํํ๋ค๋ ๊ทธ ๋ณ์๊ฐ shared๊ฐ ๋๊ฒ ๋ค์! ์ด shared๋ ์ฑ์ ์ ์ฒด ๋ฐ์ดํฐ ๊ด๋ฆฌ๋ฅผ ๋ด๋นํ๊ฒ ๋ฉ๋๋ค.
๊ทธ๋ค์ ์ฑ ๋ธ๋ฆฌ๊ฒ์ดํธ๋ฅผ ์ ์ํด์ผํฉ๋๋ค.
// ์ฑ ๋ธ๋ฆฌ๊ฒ์ดํธ
let appDelegate = UIApplication.shared.delegate as? AppDelegate
App Delegate๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์๋ช ์ฃผ๊ธฐ ์ด๋ฒคํธ๋ฅผ ๊ด๋ฆฌํด์ฃผ๋ ๊ฐ์ฒด์ธ๋ฐ ์ฌ๊ธฐ์๋ CoreData๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด ํ์ํ context๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ์ํด ์ฌ์ฉ๋์์ด์!
// ์์์ ์ฅ์
lazy var context = appDelegate?.persistentContainer.viewContext
์ฌ๊ธฐ์ persistentContainer ๋ CoreData์ ์คํ์ ๋ํ๋ด๋ฉฐ, viewContext๋ CoreData์ ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ณ ์ฐ๊ธฐ ์ํ Main Context๋ผ๊ณ ๋ณด์๋ฉด๋ผ์!
์ด์จ๋ ์ด ๊ณผ์ ์ CoreData์ ์ ์ฅ๋ ๋ฐ์ดํฐ๋ค์ ์ฌ์ฉํ๋๋ฐ ์์ด์ ํ์ํ ์์ ์ ๋จ์ํํ๊ณ ์ค๋ณต์ ํผํ๊ธฐ ์ํด ํ๋ ๊ณผ์ ์ด๋ผ๊ณ ๋ณด์๋ฉด ๋๋๋ฐ์! Class ๊ตฌ์กฐ ์ต์๋จ์ ์์นํด์์ผ๋ฉด ๋ง์์ด ๋ ๋ ํฉ๋๋ค!
๋ ๊ณ์ ์ฌ์ฉํ ๋ฐ์ดํฐ ๋ชจ๋ธ์ ์ด๋ฆ๋ ๋ณ์๋ช ์ผ๋ก ์ ์ฅํด๋ฒ๋ฆด๊ฒ์.
// ์ํฐํฐ ์ด๋ฆ (์ฝ์ด ๋ฐ์ดํฐ์ ์ ์ฅ๋ ๊ฐ์ฒด)
let modelName: String = "TodoData"
์์ ์ฝ๋๋ฅผ ์ ๋ฆฌํด๋ณด์๋ฉด ์๋ ์ฝ๋์ ๊ฐ์ด ์์ฑ์ด ๋ฉ๋๋ค.
class ListDataManager {
// ๋ฐ์ดํฐ ๋งค๋์
static let shared = ListDataManager()
private init() {}
// ์ฑ ๋ธ๋ฆฌ๊ฒ์ดํธ
let appDelegate = UIApplication.shared.delegate as? AppDelegate
// ์์์ ์ฅ์
lazy var context = appDelegate?.persistentContainer.viewContext
// ์ํฐํฐ ์ด๋ฆ (์ฝ์ด ๋ฐ์ดํฐ์ ์ ์ฅ๋ ๊ฐ์ฒด)
let modelName: String = "TodoData"
}
Create
์ด์ ์ฝ์ด๋ฐ์ดํฐ์ ์๋ก์ด ๊ฐ์ ์ ์ฅํ๋ ์ฝ๋๋ถํฐ ์ง๋ณผ๊น์?
// TodoData๋ฅผ ์์ฑํ๋ ๋ฉ์๋
func createTodoData(title: String, date: Date) {
guard let context = context,
let entity = NSEntityDescription.entity(forEntityName: modelName, in: context) else {
return
}
// NSManagedObject ์์ฑ
let newTodoData = NSManagedObject(entity: entity, insertInto: context)
// ์์ฑ ๊ฐ ์ค์
newTodoData.setValue(title, forKey: "title")
newTodoData.setValue(date, forKey: "date")
// ๋ณ๊ฒฝ ์ฌํญ ์ ์ฅ
do {
try context.save()
print("TodoData created successfully!")
} catch {
print("Error creating TodoData: \(error)")
}
}
- guard let context = context, let entity = NSEntityDescription.entity(forEntityName: modelName, in: context) else { return }
: ์ฝ์ด ๋ฐ์ดํฐ ๋ด์์๋ ํ ๊ฐ์ง์ Entity๋ง ์กด์ฌํ๋ ๊ฒ์ด ์๋ ์ฌ๋ฌ Entity๊ฐ ์กด์ฌํ๊ธฐ ๋๋ฌธ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ ํน์ Entity๋ฅผ ๊ฐ์ ธ์ด.
- let newTodoData = NSManagedObject(entity: entity, insertInto: context)
: ์๋ก์ด ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ NSManagedObject ์์ฑ
- newTodoData.setValue(title, forKey: "title"); newTodoData.setValue(date, forKey: "date")
: ๋ฐ์ดํฐ ๋ชจ๋ธ์ ์์๋ฅผ ์ ํด์ค.
- context.save()
: ๋ฐ์ดํฐ ์ ์ฅ
Read
์ด๋ฏธ ์ฝ์ด๋ฐ์ดํฐ์ ์ ์ฅ๋์ด์๋ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด์ฌ ๋ ์ด๋ป๊ฒ ์ฝ๋๋ฅผ ์ง์ผํ๋์ง ์ดํด๋ด ์๋ค.
func getTodoListCoreData(forDate date: Date) -> [TodoData] {
var todoList = [TodoData]()
guard let context = context else {
return todoList
}
let fetchRequest: NSFetchRequest<TodoData> = TodoData.fetchRequest()
let predicate = NSPredicate(format: "date == %@", date as NSDate)
fetchRequest.predicate = predicate
let sortDescriptor = NSSortDescriptor(key: "priority", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
do {
todoList = try context.fetch(fetchRequest)
} catch {
print("Error fetching todo list data: \(error)")
}
return todoList
}
- var todoList = [TodoData]()
: ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ ์ ์ฅํด๋ ๋ฐฐ์ด
- guard let context = context else { return todoList }
: ๋ฐ์ดํฐ๊ฐ ๋ค์ด์๋ ์์์ ์ฅ์ context๋ฅผ unwrappingํ๋ ๊ณผ์
- let fetchRequest: NSFetchRequest<TodoData> = TodoData.fetchRequest()
: ๋ด๊ฐ ์๊ตฌํ๋ ๋ฐ์ดํฐ๋ฅผ ์์ฒญํ๋ ์์ฒญ์๊ตฌํ
- let predicate = NSPredicate(format: "date == %@", date as NSDate); fetchRequest.predicate = predicate
: ๋ด๊ฐ ์๊ตฌํ๋ ๋ฐ์ดํฐ์ ์กฐ๊ฑด์ ๋ด์ ๋ณ์๋ฅผ ์์ฒญ์์ ์ถ๊ฐ
- let sortDescriptor = NSSortDescriptor(key: "priority", ascending: true); fetchRequest.sortDescriptors = [sortDescriptor]
: ๋ฐ์ดํฐ๋ฅผ ์ด๋ค ์ ๋ ฌ๋ก ๋ฐ์ ์ง๋ฅผ ๋ด์ ๋ณ์๋ฅผ ์์ฒญ์์ ์ถ๊ฐ
- todoList = try context.fetch(fetchRequest)
: ์์์ ์ฅ์์๊ฒ ์์ฒญ์๋ฅผ ๋ณด๋ด์ ๋ฐ์์จ ๋ฐ์ดํฐ๋ฅผ todoList ๋ฐฐ์ด์ ์ ์ฅ
์ฝ๊ฒ ํ์ด์ ์ด์ผ๊ธฐ๋ฅผ ํด๋ณด์๋ฉด ์์์ ์ฅ์์ ๋ฐ์ดํฐ๊ฐ ๋ค์ด์๋์ง ๋๋ ํ์ธํ ๋ค์, ๋ฐ์ดํฐ๊ฐ ๋ค์ด์๋ค๋ฉด ์์ฒญ์๋ฅผ ๋ง๋ค๊ธฐ ์์ํ๋ ๊ฑฐ์ฃ . ๊ทธ ์์ฒญ์๋ ์ด๋ค ๋ฐ์ดํฐ๋ฅผ ์ด๋ค ๋ชจ์์ผ๋ก ๋ด์์ฌ ๊ฒ์ธ์ง๋ฅผ ์์ฒญํ ์ ์์ด์. ์์ฒญ์๋ฅผ ๋ค ์์ฑํ๋ค๋ฉด ์์์ ์ฅ์ํํ ์์ฒญ์๋ฅผ ๋ณด๋ด์ ๋ฐ์ดํฐ๋ฅผ ๋ฌ๋ผ๊ณ ํ๋ ๊ฑฐ์ฃ . ์์์ ์ฅ์๊ฐ ์์ฒญ์๋ฅผ ๋ด์ฃผ์๋ค๋ฉด ๊ทธ ๋ฐ์ดํฐ๋ฅผ ์๋ ์ฌ์ฉํ๋ ๊ฒ์ฒ๋ผ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค!
Delete
๋ฐ์ดํฐ๋ฅผ ์ญ์ ํ ์๋ ์์ด์! ํจ๊ป ์ฝ๋๋ฅผ ์ง๋ด ์๋ค!
func deleteTodoData(_ todoData: TodoData) {
guard let context = context else {
return
}
context.delete(todoData)
do {
try context.save()
} catch {
print("Error deleting todo data: \(error)")
}
}
์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ์ฝ๋๋ณด๋ค ๋ ๊ฐ๊ฒฐํด์ก์ฃ ?! ๋ฐ์ดํฐ์ ์กฐ๊ฑด๋ค์ ๋ฌ์์ ์์ฒญ์๋ฅผ ๋ณด๋ด๋ ๊ฒ๋ณด๋ค ๋ด๊ฐ ๊ฐ์ง๊ณ ์๋ ์ด ํ ๊ฐ์ ๋ฐ์ดํฐ๋ง ์ญ์ ํ๋ฉด ๋๊ธฐ ๋๋ฌธ์ ๊ณผ์ ์ด ์์ฃผ ๊ฐ๊ฒฐํด์ง๋๋ค.
- context.delete(todoData)
: ๋ด๊ฐ ๊ฐ์ง todoData๋ฅผ ์ญ์
- context.save()
: ์์์ ์ฅ์ ์ ์ฅ
๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ์ผ๋ ๊ผญ ๋ณ๊ฒฝํ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํด์ฃผ์ด์ผํฉ๋๋ค.
Update
๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝ์ฌํญ์ ๋ํด์ ์ ๋ฐ์ดํธํ๋ ์ฝ๋๋ ์ง๋ด ์๋ค.
์ฑ์ ๋ง๋ค๋ค๋ณด๋ฉด ๋ฐ์ดํฐ์ ์ ์ฅ๋ ๊ฐ์ ๋ฐ๊ฟ์ผํ ๋๊ฐ ์์ด์. title์ ๋ฐ๊พผ๋ค๋์ง date๋ฅผ ๋ฐ๊พผ๋ค๋์ง ๊ทธ์ ๋ฐ๋ฅธ ์ฝ๋๋ค๋ ๋ค ๋ง๋ค ์ ์์ต๋๋ค. ์ฐ์ ๊ธฐ๋ณธ์ ์ผ๋ก title์ ๋ฐ๊พธ๋ ์ฝ๋๋ฅผ ์ง๋ด ์๋ค.
func updateTodoDataTitle(_ todoData: TodoData, newTitle: String) {
guard let context = context else {
return
}
todoData.title = newTitle
do {
try context.save()
} catch {
print("Error updating todo data title: \(error)")
}
}
- todoData.title = newTitle
: title ๋ฐ๊พธ๊ธฐ
- context.save()
: ์์์ ์ฅ์ ์ ์ฅ
๋๋ฌด ์ฝ์ฃ ?! ํด๋น ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์์ ๊ทธ ๋ฐ์ดํฐ์ ํด๋นํ๋ ๊ฐ๋ง ๋ณ๊ฒฝํด์ค ๋ค context์ ์ ์ฅํด์ฃผ๋ฉด ๋๋ ๊ฒ์ ๋๋ค.
๊ทผ๋ฐ ์ Update์ Delete ๊ณผ์ ์๋ ๊ฐ์ ์์ฒญํด์ fetch ํ๋ ๊ณผ์ ์ด ์์๊น์? ๊ทธ ์ด์ ๋ ์ด๋ฏธ ์ฑ์์ ์ฐ๊ณ ์๋ ๋ฐ์ดํฐ์ด๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ด๋ฏธ ๊ฐ์ ์ฝ์ด๋ฐ์ดํฐ์์ ๊บผ๋ด์์ ์ด๋ค ๋ฐ์ดํฐ๋ฅผ ์ง์ฐ๋ ค๋ ๊ฒ์ธ์ง ์ด๋ค ๋ฐ์ดํฐ๋ฅผ ์ ๋ฐ์ดํธ ํ๊ณ ์ถ์์ง ์๊ณ ์๊ธฐ ๋๋ฌธ์ fetch ํ๋ ๊ณผ์ ์ด ํ์ํ์ง ์๋๊ฑฐ์ฃ !
์์ ๋ฐฉ์์ผ๋ก ๋ด๊ฐ ์ํ๋ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ฑฐ๋ ๋ณ๊ฒฝํ๊ฑฐ๋ ์ญ์ ํ๊ฑฐ๋ ์ป์ด์ฌ ์ ์์ด์!!
๋ค์ ์๊ฐ์ ๋ ์ธ์ธํ ๊ธฐ๋ฅ์ ๊ตฌํํ๊ณ ์๋ฌ๋ฅผ ์ก๋๋ฐ ์ง์คํด๋ณด๊ฒ ์ต๋๋ค!