티스토리 뷰

Core Data 데이터 저장하기

Car Entity를 만들어놓았으니, 데이터를 한번 저장해 보자

    let myCar: [String: Any] = ["brand": "KIA", "color": "black", "price": 3000]

뷰 컨트롤러에 다음과 같이 딕셔너리 형태의 저장하고자 하는 값을 만들어주었다

 

이전 포스팅에서 context는 인스턴스들의 변화를 추적한다고 했다. 메서드라고 생각하면 편하지 않을까?

저장하는 메서드를 사용하기 위해서 context를 사용해야 하고, context 역시 다른 인스턴스들과 함께 container에 포함되어 있다

현재 persistent container는 AppDelegate에 있다

 

AppDelegate의 persistent containser에서 context를 불러오기

// AppDelegate 불러오기
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
// AppDelegate 안에 있는 persistentContainer에서 context 가져오기
let context = appDelegate.persistentContainer.viewContext

 

context를 가져왔으니 저장하고자 하는 데이터의 entity도 불러와야 한다

entity는 데이터 모델 내에서 데이터 유형을 나타낸다고 했다

우리가 저장할 데이터의 유형을 entity와 맞추면 된다

 

Entity 불러오기

guard let entity = NSEntityDescription.entity(forEntityName: "Car", in: context) else { return }

"Car" 이름의 entity를 불러왔다

 

Object 만들기

Object가 뭘까?

Core Data에서 Object란 모델 객체(Entity)의 인스턴스다

클래스를 만들고 클래스의 인스턴스를 만드는 것처럼 Entity로 Object를 만든다고 하면 될까?

let car = NSManagedObject(entity: entity, insertInto: context)

 

object를 만들었으니 object에 값도 넣어주자

car.setValue(myCar["brand"], forKey: "brand")
car.setValue(myCar["color"], forKey: "color")
car.setValue(myCar["price"], forKey: "price")

 

이제 저장하고자 하는 Object를 만들었으니, context를 통해 저장하면 된다

 

Context를 통해 저장하기

try? context.save()

 

전체 코드를 보면 아래와 같다

override func viewDidLoad() {
    super.viewDidLoad()

    guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
    let context = appDelegate.persistentContainer.viewContext

    guard let entity = NSEntityDescription.entity(forEntityName: "Car", in: context) else { return }

    let car = NSManagedObject(entity: entity, insertInto: context)
    car.setValue(myCar["brand"], forKey: "brand")
    car.setValue(myCar["color"], forKey: "color")
    car.setValue(myCar["price"], forKey: "price")

    try? context.save()
}

 

데이터 불러오기

Entity 전체의 값을 불러오는 것은 아래와 같은 코드 한 줄이면 불러올 수 있다

let newcar = try? context.fetch(Car.fetchRequest())
print(type(of: newcar)) // Optional<Array<Car>>
print(newcar)

 

 

기본적인 저장과 불러오기 성공!

 

그런데, 저장하는 코드를 다 주석 처리한 후,

불러오는 코드만 둔 채 다시 run 하면 불러온 data의 값들이 다 fault로 나오는 걸 볼 수 있다

그럼 불러오기 코드를 다음과 같이 수정해 보자

let request = Car.fetchRequest()
request.returnsObjectsAsFaults = false
let newcar = try? context.fetch(request)
print(newcar)

해결!

Fault는 메모리에 완전히 올라오지 않은 object를 나타내는 placeHolder라고 한다 (faulting이라는 기술을 사용해서 메모리 사용 최소화)

returnsObjectsAsFaults 값은 true인 경우 NSFetchRequest를 사용해서 가져온 객체를 fault로 반환

기본값은 true인데, Core Data는 Object를 가져와서 row cache를 정보로 채우고, managed object를 faults로 반환한다

(이 부분은 다음에 더 자세하게 알아보자... TODO.......)

 

아니면 실제 값을 사용할 때에는 메모리에 올라오기 때문에 fault로 보이지 않는다

guard let newcar = try? context.fetch(Car.fetchRequest()) else { return }
newcar.forEach {
    print($0.brand, $0.color, $0.price)
}

해결!

 

참고 

https://zeddios.tistory.com/987

https://velog.io/@ssionii/Core-Data%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%84%EB%9D%BC%EB%B3%B4%EC%9E%90-3-Fetch-Data
https://developer.apple.com/documentation/coredata/nsfetchrequest/1506756-returnsobjectsasfaults

댓글