Skip to content

[week14‐2] CoreData

serena edited this page Aug 30, 2023 · 1 revision

CoreData

실험 CoreData로 데이터 생성하고 불러오기

Use CoreData를 사용하여 Project를 생성하지 않는 방법으로 해보기

CoreData 생성 순서

  1. Use CoreData를 체크하지 않은 일반 Project 생성
  2. 왼쪽 하단 + > file > Data Model 파일 생성
  3. Data Model 파일에서 Entity를 추가하고 Attribute 설정
  4. Manual/None으로 설정
5. Editor > Create NSManagedObject Subclass로 모델 swift 파일 생성 6. Model Struct 만들기 > [🍎 Apple Developer - Creating a CoreData Model](https://developer.apple.com/documentation/coredata/creating_a_core_data_model)
  • NavigationBarTitle에 Preferes Large Title
  • Tab Bar 구조 참고용

Use CoreData를 사용하여 Project를 생성하는 방법으로 해보기

-> 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()
    }
}

🍎 Apple Developer - Setting up a Core Data


CoreData에 저장한 데이터 확인하기

📒 참고 Blog


App LifeCycle에 따라 save point 고민해보기

  • 메모리에 올리와 있는 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를 활용해 Core Data에서 가져오는 데이터 필터링

  1. NSPredicate 생성자의 format 파라미터를 통해 필터링할 조건을 지정할 수 있다.
  2. managed objectrequest를 만든 후 requestpredicate 프로퍼티에 1번에서 생성한 predicate를 할당한다.
  3. 해당 request를 사용해 viewContext에서 데이터를 불러온다.

🍎 Apple Document - NSPredicate 📒 참고 Blog

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 {

    }
}