ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Swift] CoreData 사용해보기: CRUD 구현 가이드
    개발/Swift 2024. 5. 18. 13:50

    문제

    - API 네트워킹시 네트워크 문제가 있을경우 내부저장 데이터를 리턴해주는 로직 필요.

    - CoreData는 내부데이터 이므로 Repository 에서 접근 하는게 맞다고 판단 했다.

    근데 CoreData는 Appdelegate의 persistentContainer.viewContext 에 접근 해야함

    Repository -> CoreData -> Appdelegate

    이는 클린 아키텍쳐 구성상 의존성의 방향이 잘못되었다 생각

     

    해결

    - CoreData 를 사용해서 데이터를 저장 & 사용

    - Repository 생성시 viewContext를 주입받아 사용

    Coordinator 패턴이나 의존성 주입 하는 부분에서 해주면 좋을것 같다.

            let appDelegate = UIApplication.shared.delegate as? AppDelegate
            let viewContext = appDelegate?.persistentContainer.viewContext
    
            let repository = NewsRepository(viewContext: viewContext, network: NewsNetwork())
            let viewModel = ViewModel(repository: repository)
            let viewController = ViewController(viewModel: viewModel)
            let rootVC = UINavigationController(rootViewController: viewController)
    
    

     

    구현

    • CoreData Entity 설정은 이미 해둠

    삭제

        private func deleteAllNewsCoreData() {
            let fetchRequestResult: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "NewsItem")
    
            let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequestResult)
            do {
                try viewContext?.execute(deleteRequest)
                try viewContext?.save()
            } catch let error {
                print("deleteAllNewsCoreData Error - \\(error)")
            }
           
        }
    

    NewsItem 엔티티 저장된 리스트 모두 지워버림

     

    저장

        private func saveNewsCoreData(news: [News]) {
            guard let viewContext = viewContext,
                let entity = NSEntityDescription.entity(forEntityName: "NewsItem", in: viewContext) else { return }
          
            news.forEach { newsItem in
                let newsObject = NSManagedObject(entity: entity, insertInto: viewContext)
                newsObject.setValue(newsItem.publishedAt, forKey: "publishedAt")
                newsObject.setValue(newsItem.title, forKey: "title")
                newsObject.setValue(newsItem.urlToImage, forKey: "urlToImage")
                newsObject.setValue(newsItem.url, forKey: "url")
            }
            do {
                try viewContext.save()
            } catch let error {
                print("saveNewsCoreData Error - \\(error)")
            }
        }
    

    객체의 데이터를 모두 꺼내서 Coredata 엔티티 생성 후 (반복) 저장

     

    읽기

        private func readNewsCoreData() -> [News] {
            let fetchRequest: NSFetchRequest<NewsItem> = NewsItem.fetchRequest()
    
            do {
                guard let result = try viewContext?.fetch(fetchRequest) else { return [] }
                let news: [News] = result.compactMap { news in
                    guard let title = news.value(forKey: "title") as? String,
                      let url = news.value(forKey: "url") as? String else { return nil }
    
                let publishedAt = news.value(forKey: "publishedAt") as? Date
                let urlToImage = news.value(forKey: "urlToImage") as? String
                    return News(title: title, url: url, urlToImage: urlToImage, publishedAt: publishedAt)
                }
                return news
            } catch let error {
                print("readNewsCoreData Error - \\(error)")
                return []
            }
    
        }
    

    Coredata 엔티티 (리스트) 꺼내와서 객체 생성후 리턴

     

     

    댓글

Designed by Tistory.