Search

'coredata'에 해당되는 글 1건

  1. 2020.12.05 CoreData

CoreData

모바일/iOS 2020. 12. 5. 13:16 Posted by 아는 개발자

CoreData는 iOS 플랫폼 단에서 지원하는 관계형 데이터베이스 라이브러리다. XCode에서 지원하는 툴과 CoreData를 사용하면 SQL의 어려운 쿼리문을 사용하지 않고도 테이블을 만들고 데이터를 추가할 수 있다. 이번 포스트에서는 Xcode를 이용해 CoreData 를 초기화하고 기본 CRUD 작업을 수행하는 것을 다뤄보려고 한다.

 

1. Data Model 파일 생성 및 초기화

 

CoreData를 사용하려면 Data Model 타입의 파일을 하나 생성해야한다. New File을 클릭하고 필터로 data 를 입력해서 Data Model 타입의 파일을 하나 추가한다.

 

이 작업이 완료되면 AppDelegate.swift 파일에 아래 코드를 추가해야한다. 현재 앱에서 바라보고 있는 데이터 모델을 세팅해주고 앱이 꺼지기 전에 데이터를 저장하는 콜백을 등록하는 작업이다. 여기서 추가한 변수인 persistentContainer는 나중에 ViewController에서 여기서 선언한 변수를 사용할 예정이다. 

 

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
	... 
    
    func applicationWillTerminate(_ application: UIApplication) {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
        self.saveContext()
    }

    lazy var persistentContainer: NSPersistentContainer = {
    
        let container = NSPersistentContainer(name: "DataModel")
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        return container
    }()
    
    func saveContext () {
        let context = persistentContainer.viewContext
        if context.hasChanges {
            do {
                try context.save()
            } catch {
                let nserror = error as NSError
                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
            }
        }
    }

 

2.  Entity, Attribute 추가 

 

아까 생성했던 DataModel 파일을 클릭해보면 왼쪽 하단에 Add Entitiy 라는 버튼이 있다. 현재 앱에서 관리할 테이블을 추가하는 과정이라고 봐도 될 것 같다. 클릭하면 Entity라는 이름으로 새로운 Entity가 생성된다. 용도에 맞게 이름을 변경해준다. 나는 Item이라고 정했다.

 

 

Entity를 만들고 나면 오른쪽 하단에 Add Attribute 버튼이 있는데 Entity가 가지게 될 속성을 추가하는 작업이다. SQL로 생각하면 테이블에 컬럼을 추가하는 것과 같다. 앱을 만들며 필요하다고 생각한 칼럼 값을 여기에 추가하면 된다. Item Entity에 name이라는 속성을 String 타입으로 추가했다. 오른쪽 패널에 이 속성에 특정 값들을 설정 할 수 있다. Optional이면 null을 허용한다는 뜻이고 Derived는 상속을 받는다? 인것 같다. 이거는 구상한 스키마에 따라서 결정하면 될 것 같다.

 

속성을 모두 업데이트 하면 Entity의 오른쪽 패널을 통해 Entity에 대한 속성을 설정 할 수 있다. Module은 Entity로부터 파생되는 Class가 사용되는 모듈을 설정하는데 특별한 경우가 아니면 현재 프로덕트 모듈(Current Product Module)로 변경해준다. Codegen은 Entity가 필요한 클래스를 자동 생성할지(Class Definition) 아니면 커스텀하게 생성할 지 (Category/Extension)을 결정하는 작업이다. Category/Extension을 사용하는 경우 직접 클래스를 만들어야하기 때문에 아직 CoreData를 공부하는 입장에서는 Class Defnition을 먼저 사용해보는게 좋다.

 

 

3. CRUD 

 

3.1 CREATE

 

DataModel 작업을 마치면 ViewController에서 아까 만든 Entity를 직접 데이터로 추가하는 작업이 남았다.  먼저 새로운 Entity를 추가하는 코드를 보자. 아래 코드는 Alert view에서 Item의 이름을 받아와 새로 추가하는 작업이다. 코드 중간부분을 보면 newItem 이라는 새로운 변수를 추가했는데 생성자로 사용한 클래스가 Item이다. 이 Item 클래스는 이전에 Data Model에서 추가한 Entity랑 이름이 같다. 이 생성자에서는 context라는 인자를 받는데 AppDelegate 클래스에서 선언한 persistentContainer 변수의 속성인 viewContext를 상용한다. 그다음 context.save() 함수를 호출해서 이 값을 통해 Item 변수를 새롭게 추가할 수 있다. 이것만 해주면 된다. SQL처럼 insert 어쩌고 저쩌고 쿼리를 날릴 필요가 없어서 간편하다.

 

@IBAction func addButtonPressed(_ sender: Any) {
    
    var textField = UITextField()
    
    let alert = UIAlertController(title: "Add New Todoey Item", message: "", preferredStyle: .alert)
    
    let action = UIAlertAction(title: "Add Item", style: .default) { (action) in
        // what will happend once user clicks the Add Item button on our UIAlert
        
        let container = (UIApplication.shared.delegate as! AppDelegate).persistentContainer
        let context = container.viewContext
        let newItem = Item(context: context)
        newItem.name = textField.text!
        self.itemArray.append(newItem)
        
        do {
            try context.save()
        } catch {
            print("Error saving contet \(error)")
        }

 

3.2 READ 

 

DataModel에서 만든 Entity에는 모두 fetchRequest() 라는 함수가 있는데 이 함수는 Entity에 해당하는 데이터를 읽어올 수 있는 select Request 쿼리를 갖고 있다. 따로 변수로 만들어서 생성 작업과 동일하게 context를 불러오고 fetch 함수 내에 request를 인자로 넣으면 데이터를 읽어올 수 있다.

func loadItems() {
    let request: NSFetchRequest<Item> = Item.fetchRequest()
    
    let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    
    do {
        itemArray = try context.fetch(request)
    } catch {
        print("error fetching data from context \(error)")
    }

 

3.3 UPDATE 

 

수정작업은 CoreData로부터 받아온 클래스의 속성 값을 수정하고 save를 호출하는 작업으로 이뤄진다. 이것 또한 복잡한 쿼리를 넣을 필요 없이 간단히 수정이 가능하다.

 

func updateItem(item: Item) {
    item.name = "update name"
    
    do {
        try context.save()
    } catch {
        print("error fetching data from context \(error)")
    }

 

3.4 DELETE 

 

삭제도 크게 다르지 않다. CoreData로부터 받아온 클래스를 context.delete의 인자로 넣어주고 save를 호출한다. 이렇게만 하면 데이터가 삭제된다.

 

func delete(item: Item) {
    context.delete(item)
    
    do {
        try context.save()
    } catch {
        print("error fetching data from context \(error)")
    }

 

4. 총평 

 

복잡한 쿼리를 짤 필요가 없어서 간편하긴 한데 Xcode 특유의, 마우스를 활용한 작업이 많아서 그런가 익숙해지려면 시간이 좀 걸릴 것 같은 느낌이다. 속성같은 것들은 키보드로 설정하는게 더 간편하고 직관적인데 말이다.

728x90

'모바일 > iOS' 카테고리의 다른 글

Realm  (0) 2020.12.05
CoreData  (0) 2020.12.05
UserDefaults  (0) 2020.12.05
IQKeyboardManager  (0) 2020.11.30
URLSession  (0) 2020.11.30
Pod  (0) 2020.11.30