본문 바로가기

iOS

[iOS] CoreData 1편(Create&Read 코드 구현)

# 코어데이터

나는 여자친구에게 선물을 주려고 선물을 박스안에 포장하고있다고 가정을해보자

그러면 선물을 에어팟과 편지 그리고 과자등등을 줄건데 그냥 이체로 주면 지저분하고 보기 안좋을 수있다.

그래서 한 포장지 상자안에 넣고 선물을 해주면 전달하기가 편하고 받기도 편할것이다. 크크

코어데이터값을 전달할때도 비슷하다.

전달하고싶은 Model data를 persistentceContainer의 context에 실어 넣고 이 실은 데이터 뭉치를 메서드를 이용해서 coreData에 저장하면된다.

솔직히 비유가 적절한지 잘모르겠으나 ㅋㅋㅋ 일단 coreData를 계속해서 알아보면서 이해할 수 있을것이다.

그러면 코드 구현순서를 알아보자

크게 섹터를

  • CoreData를 셋팅하고 값을 저장하고 값을 가져오는 방법
  • 값을 update하고 Delete해보기
    이렇게 두가지 로 나눠서 알아볼것이다.

가보자!

# CoreData를 셋팅하고 값을 저장하는 방법

  1. 일단 CoreData에 저장할 모델을 정의하기위해 Entity를 정의해줘야한다.

 

이는 CoreData모델 파일을 만들어서 Entity를 추가해주고 Attribute도 추가해주면된다.

  1. 정확한 이유는 모르겠지만 이에 맞는 SubClassModel들을 만들어준다. 추측해보기로는 만들어진 이 서브클래스 모델을 통해서 직접적으로 값을 저장할 수 있는게 아닌가 생각해본다.

DataModel파일 클릭후 Editor -> create NSManagerObject Subclass를 클릭해서 자동생성해준다.

  1. 그러면 이제 여러 VC에서 접근해서 값을 저장 해줄수 있도록 싱글톤으로 PersistentManager를 만들어보자

첫번째로 해야할건 CoreData에 접근할 persistentContainer 인스턴스를 생성한다.

컨테이너의 이름은 우리가 Entity를 만들어준 이름을 넣어주면 되겠죠? 왜냐하면 Entity의 속성들로 CoreData에 저장을 해줄거기때문에!

두번째로 데이터는 하드웨어에 저장되있는데 이를 접근해서 사용하려면 중간단계를 거쳐야한다고했쬬?
그게 Context이기때문에 Container에 값을 바꿀 viewContext를 만들어줍니다.

세번째로 저장할 메서드를 만드는것인데요 이메서드내부에 로직을 천천히 하나하나 톺아봅시다.

먼저 Entity정보를 가져와서 저장을 해줍니다. 왜냐하면 Context에 저장하기위한 Model Entity가 필요하기때문이죠
NSEntityDEscription.entity(forEntityNAme: Diary, in: viewContext)

그다음
저장할 사용자의 model이 담긴 NSManagetObject 객체를 만들어주고 전에 만든 Entity정보를 할당해줍니다.
이때 기본 entity설정은 기본값을 넣고 따로 Model파일을 생성하나 값을 받아서 setValue에 넣어줍니다.

위와 같은 두단계를 거치는 이유는 우리가 Model파일을 따로 생성해서 값을 저장해주는 방식이 아닌

만든 Model을 CoreData Entity Model형식으로 바꿔서 값을 저장해줘야하기때문이죠.

좀 말이 어려운가요 ??

쉽게 말해서 CoreData Entity Model 과 유사하게 실제 사용할 Model을 추가로 만들어주는 것이죠
그래서 저장할떄는 사용할 Model의 속성값을 NSmanagedObject 인스턴스에 setValue해서 넣어주는것!

어렵다면 코드로 살펴보시죠!

# [형식]

// 저장하는 메서드이며 매개변수로 사용할 Model을 받아옵니다.
  func saveContext(userData: userDataType) {
    // entity를 가져온다
    let entity = NSEntityDescription.entity(forEntityName: "EntityModelName", in: viewContext)
    
    if let entity = entity {
      
      // NSManagerObject를 만든다.
      
      let userModel = NSManagedObject(entity: entity, insertInto: viewContext)
      
      userModel.setValue(userData.Attribute1, forKey: "Attribute1")
      userModel.setValue(userData.Attribute2, forKey: "Attribute2")
      userModel.setValue(userData.Attribute3, forKey: "Attribute3")

 

# [실제코드]

class CoreDataController {
  static let shared = CoreDataController()
  private init() {}
  
  // 1. coreData에 접근할 persistentContainer를 인스턴스를 생성한다.
  lazy var persistentContainer: NSPersistentContainer = {
    let container = NSPersistentContainer(name: "XCDiaryModel")
    container.loadPersistentStores { description, error in
      if let error = error {
        fatalError()
      }
    }
    return container
  }()
  
  // 2. 데이터를 조작할때 필요한데 Container를 바꿀 값을 여기에 저장하는것( CRUD )
  private var viewContext: NSManagedObjectContext {
    return persistentContainer.viewContext
  }
  
  func saveContext(userData: DiaryModel) {
    // entity를 가져온다
    let diaryEntity = NSEntityDescription.entity(forEntityName: "Diary", in: viewContext)
    
    if let diaryEntity = diaryEntity {
      
      // NSManagerObject를 만든다.
      
      let userModel = NSManagedObject(entity: diaryEntity, insertInto: viewContext)
      
      userModel.setValue(userData.identifier, forKey: "identifier")
      userModel.setValue(userData.title, forKey: "title")
      userModel.setValue(userData.body, forKey: "body")
      userModel.setValue(userData.createdAt, forKey: "createdAt")
      
      // viewContext를 저장
      
      guard viewContext.hasChanges else { return }
      
      do {
        try viewContext.save()
      } catch let error as NSError {
        print("Error: \(error), \(error.userInfo)")
      }
    }
  }
}
 

조금 이해가 되실까요 ?

그리고 이 작업이 끝났으면 마지막으로 해줘야할 작업이있습니다.

바로 저장하기!!

ViewContext를 저장하기인데요
그전에!! 변경여부확인을 먼저 해줍시다.

viewContext.hasChages라는 프로퍼티를 사용해서 값이 변경이 되어있으면 false를 반환하고 변경이되있으면 true를 반환하기때문에 한번 저장하기전에 확인해주는 단계를 거칩니다.

이제 마지막으로 viewContext.save()를 실행해주면되죠.

그러면 끝!! 저장하기 싱글톤 객체만들기는 끝났습니다.

실제로 이를 VC에서 사용할때는 PersistentControllet.saveContext(userModel:)이메서드를 호출해서 값을 저장할 Model타입을 매개변수에 할당만 해주면 되는것이죠!!

어렵지않죠??

# 이번엔 CoreData에 저장한 정보를 fetch해서 가져와봅시다.

이부분은 정말 쉬운게 우리가 CoreDataModel파일을 만들면서 서브클래스를 만들었잖아요 ???

바로 요기!!
위에 자동으로 생성되면서 fetchRequest메서드도 생성이된게보이시죠 ??

이걸 사용해서 데이터를 가져오기만 하면됩니다. ㅎㅎ

  // 만들어져있는 Diary의 fetchRequest메서드를 이용해서 값을 가져와준다.
  func fetchContext() -> [Diary] {
    do {
      let users = try viewContext.fetch(Diary.fetchRequest())
      return users
    } catch {
      fatalError()
    }
  }