iOS) Core Data
Core Data 에 대해서
Core Data 는 iOS 기본 프레임워크이다.
UserDefaults 는 app setting 같은 간단한 정보를 저장하기에 적합하다면
Core Data 는 복잡하고 큰 user data 를 저장하기에 적합하다. 예를 들어 내 아이폰 내에서의 검색 기록과 같이 시간과 키워드에 해당하는 정보를 저장하기에 UserDefaults 보다 적합할 수 있다.
‘Core Data 는 Database 인가?’
아니다. 데이터를 유지하기 위한 API 도 아니다. 객체 그래프를 관리하는 Framework 이다.
이 객체 그래프를 디스크에 저장하여 Persistence 기능을 이용할 수 있는 것이다.
보통 영구적으로 저장하기 위해서 Core Data 를 사용하는데 Persistence 는 Core Data 의 기능 중 하나일뿐이다. 그렇기 때문에 Persistence 기능을 사용하지 않고도 Core Data 를 이용할 수 있다.
Core Data 가 속한 Core Service 계층과 다른 계층을 iOS Architecture 를 알아보자
Cocoa Touch
- 화면의 그래픽 UI 및 터치의 기능을 제공하는 Framework
- UIKit, MapKit, GameKit, MessageUI, MessageUI, AddressBookUI
Media
- 그래픽이나 오디오, 비디오 등 멀티미디어의 기능을 제공하는 Framework
- AvFoundation, MediaPlayer, Core Animation, Core Graphics
Core Service
- GPS 나침반, 가속도 센서나 자이로스코프 센서와 같이 디바이스의 하드웨어 특성에 기반한 서비스 제공
- Core Location, Core Data, Core Motion, Foundation
Core OS
- 하드웨어와 가장 가까이 있는 최하위 계층
- C 기반의 저수준의 API로 이루어져 있음.
- 커널, 파일 시스템, 전원 관리, 디바이스 드라이버 등이 포함
Core Data
단일장치에 대한 캐시데이터 유지 혹은 CloudKit 을 사용해서 여러장치에 데이터 동기화
Overview
Core Data 를 사용해서 데이터의 오프라인 사용, 임시데이터 캐시, 단일기기에서 undo functionality 추가한다.
단일 iCloud 계정에서 여러장치에서 데이터를 동기화힉 위해서 Core Data 는 자동으로 스키마를 Cloud kit container 에 미러링한다.
Core Data 의 Data Model editor 를 통해서 데이터의 types, relationships 와 각 class 의 정의를 생성합니다. Core Data 는 런타임때 객체 인스턴스를 관리해서 다음과 같은 기능을 제공할 수 있다.
Persistence
Core Data 는 객체를 저장소에 매핑하는 세부정보를 추상화해서 데이터베이스를 직접 관리하지 않고도 Swift 와 Objective-C 의 데이터를 쉽게 저장할 수 있다.
Undo and Redo of Individual or Batched Changes
Core Data 의 undo manager tracks 는 변경 사항을 추적해서 개별적, 그룹, 한번에 모두 롤백할 수 있어서 쉽게 undo(실행취소), redo(다시 실행)지원을 앱에 추가할 수 있다.
Background Data Tasks
background 에서 JSON 을 객체로 파싱하는 것과 같이 잠재적으로 UI-blocking data tasks 를 수행한다. 그런다음 결과를 캐시하거나 저장하여 서버 왕복을 줄일 수 있다.
View Synchronization
Core Data 는 table 과 collection views 의 data sources 를 제공함으로써 뷰와 데이터를 동기화 상태로 유지하는것 역시 도움이 된다.
Versioning and Migration
Core Data 는 data model 의 versioning 과 앱이 발전함에 따라 user data 를 migrating 한다.
(Core Data 는 현재 data model 을 가장 최신으로 유지하는데 도움이되는 built-in data migration tool 이 있다.)
Core Data Apple Developer Documentation
Core Data Stack
app’s model layer 관리, 유지
Overview
Core Data 는 app’s model layer 을 공동으로 지원하는 클래스 집합을 제공한다.
NSManagedObjectModel
의 인스턴스는 properties 와 relationships 를 포함하여 app’s types 를 설명한다.-
NSManagedObjectContext
의 인스턴스는 app’s types 의 인스턴스에 대한 변화를 추적한다. 이 객체를 통해서 create, delete, fetch, update 작업을 할 수 있다.(core data는 메모리에 로드된 상태로 처리되는데, 이 때의 메모리가 context 를 의미)
-
NSPersistentStoreCoordinator
의 인스턴스는 store 에서 app’s types 의 인스턴스를 저장하고 가져온다.(Context 와 Container 사이를 통신한다.)
출처 : https://developer.apple.com/documentation/coredata/setting_up_a_core_data_stack
출처 https://www.vadimbulavin.com/core-data-stack-swift-4/
NSPersistentContainer
인스턴스를 사용해서 model, context, store coordinator 를 동시에 설정한다.
(전체적으로 관리하는 최상단의 객체)
Core Data Stack Apple Developer Documentation
Setting Up a Core Data Stack
Initialize a Persistent Container
일반적으로 app’s startup 동안 Core Data 가 초기화된다. persistent container 를 lazy variable
로 만들어서 delegate 에서 처음 사용할때까지 연기시킨다.
새 Xcode 프로젝트를 생성할 때 Core Data checkbox 를 선택했다면 AppDelegate
에 setup code 가 자동으로 포함되어있을 것이다.
NSPersistentContainer
를 lazy variable 로 선언.- data model filename 를 이니셜라이저에 전달해서 persistent container instance 를 생성
- persistent stores 를 로드한다. 존재하지 않을 경우 store 를 만든다.
class AppDelegate: UIResponder, UIApplicationDelegate {
...
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "DataModel")
container.loadPersistentStores { description, error in
if let error = error {
fatalError("Unable to load persistent stores: \(error)")
}
}
return container
}()
...
}
생성되면 persistent container 는 해당 managedObjectModel
, viewContext
, persistentStoreCoordinator
속성에 각각 model, context, store coordinator 인스턴스에 대한 참조를 가진다.
NSPersistentContainer 정의.
container 에 대한 참조를 user interface 에 전달할 수 있다.
Pass a Persistent Container Reference to a View Controller
app’s root view controller 에서 Core Data 를 import 하고 persistent container 참조하는 변수를 만들어라
import UIKit
import CoreData
class ViewController: UIViewController {
var container: NSPersistentContainer!
override func viewDidLoad() {
super.viewDidLoad()
guard container != nil else {
fatalError("This view needs a persistent container.")
}
// The persistent container is available.
}
}
delegate 로 돌아간다. application(_:didFinishLaunchingWithOptions:)
에서 app window’s rootViewController 을 root view controller type 으로 downcast 한다.
class AppDelegate: UIResponder, UIApplicationDelegate {
...
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if let rootVC = window?.rootViewController as? ViewController {
rootVC.container = persistentContainer
}
return true
}
...
}
persistent container 를 추가적인 view controllers 에 전달하려면 각 뷰컨에서 container variable 생성을 반복하고 이전 뷰컨의 prepare(for:sender:)
에서 해당 값을 설정한다.
class ViewController: UIViewController {
...
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let nextVC = segue.destination as? NextViewController {
nextVC.container = container
}
}
}
Subclass the Persistent Container
NSPersistentContainer
는 subclass 로 지정된다. subclass 는 subset of data 와 data 를 디스크에 유지하기위한 호출과 같은 Core Data 관련 코드를 넣을 수 있는 장소다.
import CoreData
class PersistentContainer: NSPersistentContainer {
func saveContext(backgroundContext: NSManagedObjectContext? = nil) {
let context = backgroundContext ?? viewContext
guard context.hasChanges else { return }
do {
try context.save()
} catch let error as NSError {
print("Error: \(error), \(error.userInfo)")
}
}
}
위의 코드는 변경사항이 있을때만 context 에 저장해서 성능을 향상시키기 위한 saveContext
함수를 추가하는 예시이다.
Setting Up a Core Data Stack Apple Developer Documentation
Creating a Core Model
Creating a Core Model Apple Developer Documentation