-
Notifications
You must be signed in to change notification settings - Fork 0
[week14‐2] CoreData
serena edited this page Aug 30, 2023
·
1 revision
- Use CoreData를 체크하지 않은 일반 Project 생성
- 왼쪽 하단 + > file > Data Model 파일 생성
- Data Model 파일에서 Entity를 추가하고 Attribute 설정
- Manual/None으로 설정
- NavigationBarTitle에 Preferes Large Title
- Tab Bar 구조 참고용
-> AppDelegate에 NSPersistentContainer를 생성하여 해보기
class AppDelegate: UIResponder, UIApplicationDelegate {
// MARK: - Core Data stack
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "test")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
// MARK: - Core Data Saving support
func saveContext () {
let context = persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
}
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func sceneDidEnterBackground(_ scene: UIScene) {
(UIApplication.shared.delegate as? AppDelegate)?.saveContext()
}
}
- 메모리에 올리와 있는
data
를 디스크에 저장하는 것을 CRUD를 진행하는 모든 메소드에서 하는 것이 과연 효율적일까 하는 의문이 들었다 -
data
를 메소드에서 저장하는 것이 아닌 특정 포인트에서 몰아서 저장함으로 디스크에 저장하는 액션의 횟수를 최소화하기위해 몇가지save point
를 고민해봤다viewWillDisappear
deinit
sceneDidEnterBackground
- 앱이 background로 가는 순간인
sceneDidEnterBackground
가 최종 저장 포인트로 적합하다고 생각했다- 앱을 바로 종료할 경우
View LifeCycle
(viewWillDisappear
,viewDidDisappear
,deinit
) 메서드들이 동작 완수를 보장하지 않기 때문 - 홈으로 나갈 때
sceneDidEnterBackground
는 확실하게 수행됨
- 앱을 바로 종료할 경우
- 하지만 앱 실행 중간에 오류가 날 수 있다는 점을 고려했을 때, save point를 하나만 주는 것은 위험하다고 생각한다
- 따라서 CRUD를 진행하며 저장까지 수행하는 것이 안전한 방법이라고 생각한다.
// TableView에서 Cell delete 수행 후 저장 예시
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let deleteAction = UIContextualAction(style: .destructive, title: "delete") { [weak self] contextualAction, view, completion in
guard let managedObject = self?.jokeManagedObjects[indexPath.row] else {
completion(false)
return
}
self?.container.viewContext.delete(managedObject)
do {
try self?.container.viewContext.save()
} catch {
}
self?.getAllItems()
completion(true)
}
return UISwipeActionsConfiguration(actions: [deleteAction])
}
-
NSPredicate
생성자의format
파라미터를 통해 필터링할 조건을 지정할 수 있다. -
managed object
의request
를 만든 후request
의predicate
프로퍼티에 1번에서 생성한predicate
를 할당한다. - 해당
request
를 사용해viewContext
에서 데이터를 불러온다.
func getAllItems() {
do {
guard let category = tabBarController?.tabBar.selectedItem?.title else {
return
}
let request = Joke.fetchRequest()
let predicate = NSPredicate(format: "category == %@", category)
request.predicate = predicate
jokeManagedObjects = try container.viewContext.fetch(request)
tableView.reloadData()
} catch {
}
}