Coredata

1 답변 글타래를 보이고 있습니다
  • 글쓴이
    • lidium
      참가자
      • 글작성 : 9
      • 답글작성 : 8

      서버를 안쓰고 내부DB를 사용하는 방식으로 프로젝트를 기획하고 있습니다.
      여러개의 후보군이 있는데,
      1) Coredata
      2) UserDefault
      3) SQLite (FMDB)
      등이 있습니다.
      오늘은 Coredata를 이용해서 내부DB를 사용해볼 것입니다!
      Coredata는 iOS 10 이상의, 특정 템플릿에서 Coredata를 지원하는데, 이 중 SingleView App은 Coredata를 지원하니
      이를 이용해서 실습을 해볼 것입니다.
      실습은 https://www.raywenderlich.com/7569-getting-started-with-core-data-tutorial 을 통해서 했습니다.


      프로젝트 설정창 하단부의 Coredata를 선택하면, 오른쪽과 같이 Xcdatamodeld이라는 확장자를 가진 파일이 생성됩니다.
      Xcdatamodeld를 누르면 원래는 아무것도 없을텐데, 하단부의 Add Entities를 누르면 Entity를 생성할 수 있습니다.
      코어데이터를 사용할 때 해야 할 필수적인 몇가지가 있는데
      AppDelegate의 managedObjectContext와, xcdatamodeld,
      ✅NSManagedObject와 NSPersistentContainer ✅가 있습니다.
      ✅NSManagedObject
      A base class that implements the behavior required of a Core Data model object.
      Coredata의 모든 데이터의 생성, 제거, 수정을 하기 위해서 해당 객체를 사용해야만 합니다. 임의의 entity를 나타낼 수 있습니다.
      ✅NSPersistentContainer
      A container that encapsulates the CoreData stack in your app.
      이 컨테이너를 통해 NSManagedObject 객체들을 다룰 수 있게 합니다. 프로젝트를 만들 때 Use Core Data를 선택하면
      AppDelegate에 아래와 같이 선언이 됩니다.

       lazy var persistentContainer: NSPersistentContainer = {
      let container = NSPersistentContainer(name: "HitList")  // name은 entity의 이름
      container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
      fatalError("Unresolved error \(error), \(error.userInfo)")
      }
      })
      return container
      }()
      

      코어데이터를 사용하고자 하는 곳에, 빈 NSManagedObject를 선언해 주어야 합니다.
      해당 방법과 같이 Coredata 내부 데이터를 다룰 수 있습니다.

      var models: [NSManagedObject] = [NSManagedObject]()
      let name: String = models.first?.value(forKey: "name") as? String
      

      Key Value Coding : KVC에 대한 언급!
      NSManagedObject는 name attribute를 알 수 없고, 따라서 attribute를 직접 가져올 수 없어서,
      Key Value Coding을 통해서만 값을 읽을 수 있습니다.
      다음은 코드 리뷰입니다!
      저장하는 함수 save입니다. 이 함수가 실행되면 내부DB에 String이 저장됩니다.

      func save(name: String) {
      guard let appDelegate =
          UIApplication.shared.delegate as? AppDelegate else {
          return
        }
      // 1
        let managedContext =
          appDelegate.persistentContainer.viewContext
      // 2
        let entity =
          NSEntityDescription.entity(forEntityName: "Person",
                                     in: managedContext)!
      let person = NSManagedObject(entity: entity,
                                     insertInto: managedContext)
      // 3
        person.setValue(name, forKeyPath: "name")
      // 4
        do {
          try managedContext.save()
          people.append(person)
        } catch let error as NSError {
          print("Could not save. (error), (error.userInfo)")
        }
      }
      

      ✅ entity 이름 : person, attribute 이름 : name ✅

      1. Delegate 선언을 통해, persistentContainer를 받아옵니다. viewContext는 persistentContainer의 ReadOnly 변수입니다.
        ManagedObjectContext를 선언하여 managed object를 담아놓습니다.
        이를 ‘Commit’ 해야 디스크에 저장이 됩니다.
      2. NSManagedObject를 이용하여 Coredata 내부의 entity를 받아옵니다.
      3. NSManagedObject를 2번에서 얻었으니, key-value coding을 사용해 name attribute를 설정합니다.
        반드시 KVC 키(이 경우에는 name)이 Data Model 에 있는것과 일치해야 합니다.
      4. managedContext.save()는 반드시 do – catch 문에서 이뤄져야 합니다. save는 에러가 발생할 수 있기 때문입니다.

      다음은, 디비에서 fetch를 해 옵시다.

      override func viewWillAppear(_ animated: Bool) {
          super.viewWillAppear(animated)
      // 1
      guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
        return
      }
      // 2
      let managedContext = appDelegate.persistentContainer.viewContext
      let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Person")
      // 3
      do {
        people = try managedContext.fetch(fetchRequest)
      } catch let error as NSError {
        print("Could not fetch. (error), (error.userInfo)")
      }
      

      fetch라고 해서 다르지 않습니다!
      과정은 비슷한데,
      1. appDelegate 선언,
      2. managedContext를 선언 ( ManagedObjectContext )
      fetchRequest : 기준을 충족하는 객체 집합을 가져오는 강력하고 유연한 함수.
      3. 역시나 fetch도 에러가 날 수 있기 때문에 do – catch문에서 사용.
      ##실행화면

      앱을 껐다가 켜도, 테이블뷰에 데이터가 살아있는 모습을 볼 수 있슴니다!
      부족한 점이 많습니다! 오개념이 있다면 지적 부탁드릴게요! 감사합니다.

    • 야곰
      키 마스터
      • 글작성 : 37
      • 답글작성 : 579

      좋은 튜토리얼이네요!
      @elesahich 님, 제목에 마트다운이 적용 안되는 이유는 샵 뒤에 띄어쓰기를 하지 않기 때문입니다.
      마크다운 에디터마다 샵 뒤에 띄어쓰기를 하지 않아도 되는 경우가 있는데, 표준 마크다운 문법에서는 띄어쓰기를 하므로, 그렇게 익혀두는 것이 나중에도 편할겁니다.

      • ##제목 (X)
      • ## 제목 (O)
1 답변 글타래를 보이고 있습니다
  • 답변은 로그인 후 가능합니다.

logo landscape small

사업자번호 : 743-81-02195
통신판매업 신고번호 : 제 2022-충북청주-1278 호
고객센터 : 카카오톡채널 @yagom