ARCHIVES

태그

신고하기

상단 메뉴 페이지

기본 콘텐츠로 건너뛰기

[Swift] CoreData 사용법

이번에 프로젝트 하면서 CoreData를 사용했다. 처음 만들고 사용하는데는 문제가 없지만

중간에 컬럼을 추가해서 사용해보니 업데이트 시 문제가 되었다. ( 컬럼 추가는 별다른 문제가 없다. )

해결법과 사용법을 정리해서 올려둔다.

코어데이터 문서 만드는법 feet.apple


일단 간단한 정리

1. 새 프로젝트라면 Use Core Data 에 체크해서 만들고

2. 기존 프로젝트 추가면 Command + N을 눌러 Data Model 추가.

---

3. .xcdatamodeld 파일에서 "Add Entity" 를 한다. Entity 이름은 중요합니다. 테이블 이름

4. 이제 Attributes 추가하고.. 등등 테이블을 만듭니다.

5. 중요: 우측의 인스펙터를 보면 "Codegen" 영역이 "Class Definition" 이라고 되어 있습니다.

여기를 그냥 사용하면 비즈니스 로직을 넣을 수 없습니다. 그래서! 보통 수동으로 바꾸죠

"Manual/None" 으로 변경하고 

상단메뉴 "Editor" -> Create NSManagedObject 합니다.

------
일단 여기까지 만들었으면 

CoreDataManager를 만들어 사용합니다. 편하게 쓰려면 한곳에 몰아 넣어야죠


AppDelegate.swift

앱델리게이트에 선언 되어 있어야 한다.

//

//  AppDelegate.swift

//  CoreDataTest

//

//  Created by jae hwan choo on 2020/09/24.

//


import UIKit

import CoreData


@main

class AppDelegate: UIResponder, UIApplicationDelegate {


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        return true

    }


    // MARK: UISceneSession Lifecycle

    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {

        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)

    }


    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {

    }

    

    // MARK: - Core Data stack

    lazy var persistentContainer: NSPersistentContainer = {

        let container = NSPersistentContainer(name: CoreDataManager.MODEL_NAME)

        container.loadPersistentStores(completionHandler: { (storeDescription, error) in

            if let error = error as NSError? {

                fatalError("Unresolved error \(error), \(error.userInfo)")

            }

        })

        return container

    }()


    // MARK: - Core Data Saving support

    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)")

            }

        }

    }



}


CoreDataManager.swift

아래와 같이 메니저 클래스를 만든다.

//

//  CoreDataManager.swift

//  CoreDataTest

//

//  Created by jae hwan choo on 2020/09/24.

//


import UIKit

import CoreData


class CoreDataManager {

    // MARK: - 변수

    static let shared: CoreDataManager = CoreDataManager()

    

    static let MODEL_NAME: String = "ErsModel"

    static let MODEL_ENTITYNAME: String = "Contact"

    

    let appDelegate: AppDelegate? = UIApplication.shared.delegate as? AppDelegate

    lazy var context = appDelegate?.persistentContainer.viewContext

    

    // MARK: - 저장

    func setPeople(_ item: ContactVo, onSuccess: @escaping ((Bool) -> Void)) {

        guard let context = context else {

            return

        }

        

        if let entity: NSEntityDescription = NSEntityDescription.entity(forEntityName: CoreDataManager.MODEL_ENTITYNAME, in: context) {

            

            if let user: Contact = NSManagedObject(entity: entity, insertInto: context) as? Contact {

                user.name = item.name

                user.age = item.age

                //user.locationName = item.phone

            }

            

            // 실제 저장

            contextSave { success in

                onSuccess(success)

            }

        }

    }

    

    

    // MARK: 목록 내보내기

    func getPeoples(ascending: Bool = false) -> [ContactVo] {

        guard let context = context else {

            return []

        }

        var models: [ContactVo] = [ContactVo]()

        

        let fetchRequest: NSFetchRequest<NSManagedObject> = NSFetchRequest<NSManagedObject>(entityName: CoreDataManager.MODEL_ENTITYNAME)

        do {

            if let fetchResult: [Contact] = try context.fetch(fetchRequest) as? [Contact] {

                for item in fetchResult {

                    let people: ContactVo = ContactVo()

                    people.name = item.name ?? ""

                    people.age = item.age ?? ""

                    models.append(people)

                }

            }

        } catch let error as NSError {

            print("Could not fetch🥺: \(error), \(error.userInfo)")

        }

        return models

    }

    

    

    // MARK: 목록 전체 삭제

    func deleteAllPeoples() {

        guard let context = context else {

            return

        }

        

        let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: CoreDataManager.MODEL_ENTITYNAME)

        let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)

        

        do {

            try context.execute(deleteRequest)

        } catch let error as NSError {

            print("Could not fetch🥺: \(error), \(error.userInfo)")

        }

    }

    

    

    fileprivate func contextSave(onSuccess: ((Bool) -> Void)) {

        do {

            try context?.save()

            onSuccess(true)

        } catch let error as NSError {

            print("Could not save🥶: \(error), \(error.userInfo)")

            onSuccess(false)

        }

    }

}

ViewController.swift

아래와 같이 사용한다.

//

//  ViewController.swift

//  CoreDataTest

//

//  Created by jae hwan choo on 2020/09/24.

//


import UIKit


class ViewController: UIViewController {


    override func viewDidLoad() {

        super.viewDidLoad()

        

        CoreDataManager.shared.setPeople(ContactVo("kim","16")) { (bool) in

            // 저장성공

        }

        

        let datas = CoreDataManager.shared.getPeoples()

        for item in datas {

            print("이름 \(item.name)")

        }

    }

}



정상동작을 확인하고

이제 컬럼을 추가 해서 테스트 해본다.

...

...

...


그냥 된다. ㅠㅠ

방어 코드로 "AppDelegate.swift" 에서 Auto 마이그레이션 코드를 넣는다.

    // MARK: - Core Data stack

    lazy var persistentContainer: NSPersistentContainer = {

        let container = NSPersistentContainer(name: CoreDataManager.MODEL_NAME)

        container.loadPersistentStores(completionHandler: { (storeDescription, error) in

            if let error = error as NSError? {

                fatalError("Unresolved error \(error), \(error.userInfo)")

            }

        })

        // 코어 데이터가 변경 된 경우 마이그레이션 Auto  추가

        let description = NSPersistentStoreDescription()

        description.shouldInferMappingModelAutomatically = true

        description.shouldMigrateStoreAutomatically = true

        container.persistentStoreDescriptions.append(description)

        

        return container

    }()




일단
여기서 완료 하고 종료 한다.

문제 생기면 다시 온다...


3시간뒤... 코어데이터 문제가 아니었다.
비즈니스 로직 변경으로 이슈 해결.

댓글