ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • iOS) Core Data (3) - CRUD
    iOS 2021. 1. 27. 14:21

    전에 생성 했던 Entity Class를 이용하여 데이터를 생성하고 읽고 업데이트하고 삭제 하는 기능을 구현 해보자.

     

    Core Data Model에서 Codegen를 Manual/None으로 바꿔준 후 Xcode의 NSManagedObject Class를 생성 하는 기능으로 Entity Class를 생성 해주었다.

     

     DataManager를 extension 하여 CRUD 기능을 만들어 보자. 또 Entity Class가 아닌 Xcode에서 자동으로 생성 해주었던 Entity와 어떻게 다른지 비교해 보자.

     

    CREATE

    extension DataManager {
    
        func createPerson(name: String, age: Int?) {
            mainContext.perform {
                let newPerson = PersonEntity(context: self.mainContext)
                newPerson.name = name
                if let age = age {
                    newPerson.age = Int16(age)
                }
                
                self.saveMainContext()
            }
        }
    }
    

    createPerson 메소드는 새로운 Person Entity를 만든 후 context를 통해 저장하는 기능을 가지고 있다.

     

    context는 PersistentContainer의 viewContext이다.

    정의를 보면

    The managed object context associated with the main queue.

    즉 메인 큐에서 돌아가는 관리 받는 객체 context란 뜻이다.

    메인큐에서 돌아간다는 뜻은 context가 쓰레드에 영향을 미치므로 'perform' 블록을 통해 실행 되는 것들도 메인큐에서 실행 되도록 하여 쓰레드에 문제를 야기하지 않도록 하는 것이 편하다.

     

    자동으로 생성 되는 Entity Class의 경우 

    let newEntity = NSEntityDescription.insertNewObject(forEntityName: "Person", into: context)
    newEntity.setValue(name, forKeyPath: "name")
    newEntity.setValue(age, forKeyPath: "age")

    이와 같이 새로운 Entity 생성시 Entity의 이름을 명시 해줘야 하며 attribute도 setValue 방식으로 생성하기 때문에 오류를 야기한다.

     

    READ

    모델에서 데이터를 가져오는 것을 fetch라고 한다.

    아래의 메소드 fetchPerson은 PersonEntity의 배열을 리턴해주고 context의 perform 메소드는 배열을 바로 리턴 해줄 수 없다. 

    따라서 배열 전체가 리턴 될때 까지 기다렸다가 리턴 해주는 performAndWait 메소드를 사용해준다.

     

    context에게 fetch를 요청하는 request는 Entity Class에 선언 된 fetchRequest 메소드를 사용 해주어서 더욱 간단해졌다.

    sortByName은 fetch 되는 데이터를 정렬 해주는 코드이다.

    func fetchPerson() -> [PersonEntity] {
            var list = [PersonEntity]()
            mainContext.performAndWait {
                let request: NSFetchRequest<PersonEntity> = PersonEntity.fetchRequest()
                let sortByName = NSSortDescriptor(key: #keyPath(PersonEntity.name), ascending: true)
                request.sortDescriptors = [sortByName]
                do {
                    list = try mainContext.fetch(request)
                } catch {
                    print(error)
                }
            }
            return list
        }

    Entity Class를 사용하지 않을 경우 attribute에 대한 접근에 있어서 setValue를 사용 해야 해서 이 또한 어려웠다.

     

    UPDATE

    기존 모델의 Entity를 가져와 새로운 데이터로 업데이트 해주는 메소드이다.

    func update(entity: PersonEntity, name: String, age: Int?) {
            mainContext.perform {
                entity.name = name
                if let age = age {
                    entity.age = Int16(age)
                }
                
                self.saveMainContext()
            }
        }

     

    DELETE

    func delete(entity: PersonEntity) {
            mainContext.perform {
                self.mainContext.delete(entity)
                self.saveMainContext()
            }
        }

     

     

    Xcode가 Entity Class를 생성하는 패턴

     

    Create NSManagedObject SubClass를 사용해 Entity Class를 생성할 때 Entity Class와 Entity Class의 extension 파일이 두 개 생긴다.

    이는 모델의 확장과 관련있다.

    모델의 내용이 변경 되었을 때 class파일은 계속 유지 되고 extension 파일만 업데이트 된다.

    즉 attribute가 추가 되었을때 Extension 부분만 바뀌고 기존 Entity Class파일은 바뀌지 않는다. 따라서 기능을 구현 할 때는 class에서 구현 해준다.

     

    Codegen

    Manual/None - Entity Class 직접 생성

    Class Definition - Entity Class 자동 생성 (Manual/None을 통해 직접 Entity Class 생성 했다면 오류가 난다. Entity Class를 지워야만 정상 빌드) Entity Class에 별도의 기능을 추가 할 필요가 없을때 사용

    Category/Extension - 속성이 선언 되어 있는 Entity Class가 자동으로 생성 된다. 즉, Extension의 추가 된 attribute가 자동으로 생성 되기 때문에 새로운 attribute를 추가 할 때마다 수정해 줄 필요가 없다.

     

     

    댓글

Designed by Tistory.