CoreData 프로젝트 생성 및 사용

JG Ahn·2024년 12월 4일
0

iOS

목록 보기
10/32
post-thumbnail

CoreData : 앱에서 기기의 디스크에 데이터를 읽고 쓸 수 있게 돕는 프레임워크.(CRUD)

CoreData 세팅

1. CoreData 프로젝트 생성

storage → CoreData


2. Entity 생성

  • Entity

    • 데이터베이스의 테이블과 유사
    • 데이터 모델 내에서 객체 또는 데이터 유형(Type)을 나타내며, 속성(Attribute)과 관계(Relationship)를 가짐
    • Entity와 속성들은 앱에서 저장된 데이터의 스키마 역할을 함

💡 스키마 : 데이터베이스에서 데이터 구조와 그 표현법, 자료 간의 관계를 형식 언어로 정의한 것


3. Code Generate

오른쪽 Inspectors영역에서 Codegen을 Manual/None 으로 선택

Editor → Create NSManagedObject Subclass를 클릭해서 코드 생성

  • Codegen : Code Generator의 줄임말. Entity를 어떤 형식의 코드로 생성할 것인지 선택하는 속성.

  • Codegen의 3가지 옵션

    • Manual/None : Entity의 서브클래스를 개발자가 작성
    • Class Definition : Entity의 서브클래스를 자동으로 작성
    • Category/Extension : Entity 클래스 + extension 파일 생성

[ PhoneBook+CoreDataClass.swift ]

import Foundation
import CoreData

@objc(PhoneBook)
public class PhoneBook: NSManagedObject {

}

NSManagedObject : CodeData에서 관리되는 객체를 나타내는 기본 클래스. Entity와의 상호작용을 관리하고 속성 값의 저장 및 검색 처리

[ PhoneBook+CoreDataProperties.swift ]

import Foundation
import CoreData

extension PhoneBook {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<PhoneBook> {
        return NSFetchRequest<PhoneBook>(entityName: "PhoneBook")
    }

    @NSManaged public var name: String?
    @NSManaged public var phoneNumber: String?

}

extension PhoneBook : Identifiable {

}
  • @nonobjc : swift에서만 동작하는 메소드임을 명시. Objective-C(X)
  • fetchRequest() : Entity에 대한 여러가지 데이터 검색을 도움
  • @NSManaged : CoreData에 의해 관리되는 객체를 의미
  • Identifiable : Entity 타입이 고유하게 식별될 수 있음을 의미

3. NSPersistentContainer 생성

NSPersistentContainer : CoreData에서 데이터를 저장하고 관리하는데 필요한 핵심 객체.
프로젝트 생성시 CoreData를 체크해줬기 때문에 AppDelegate.swift 에 코드가 자동으로 세팅됨

saveContext() : 데이터 업데이트시 문맥을 저장하는 메소드

CoreData를 활용한 CRUD

1. ViewController에서 AppDelegate의 persistentContainer 참조

import UIKit
import CoreData

class ViewController: UIViewController {

    //AppDelegate.swift의 NSPersistentContainer를 불러옴.
    // ! 는 반드시 사용한다 확신이 있으므로 사용
    //CoreData를 import 해줘야함
    var container: NSPersistentContainer!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        //AppDelegate로 타입캐스팅
        let appDelegate = UIApplication.shared.delegate as! AppDelegate

        //16라인의 container가 AppDelegate.swift에 있는 persistentContainer를 참조
        self.container = appDelegate.persistentContainer
        
    }
...

2. Create

ViewController에 이어서 작성

    //CoreDataPractice에 데이터 Create
    func createData(name: String, phoneNumber: String) {

        //NSEntityDescription: Entity를 정의.
        //코드를 분석해보면, phoneBook 엔티티를 container의 맥락(viewContext)으로 정의한다는 의미
        guard let entity = NSEntityDescription.entity(forEntityName: PhoneBook.className, in: self.container.viewContext) else { return }

        //위에서 만든 entity 객체를 만듦
        let newPhoneBook = NSManagedObject(entity: entity, insertInto: self.container.viewContext)

        newPhoneBook.setValue(name, forKey: PhoneBook.key.name)
        newPhoneBook.setValue(phoneNumber, forKey: PhoneBook.key.phoneNumber)

        //데이터 변조가 일어난 경우 AppDelegate의 saveContext와 같은 역할을 하는 save메소드를 사용
        do {
            try self.container.viewContext.save()
            print("문맥 저장 성공")
        } catch {
            print("문맥 저장 실패")
        }
        
    }
...

3. Read

ViewController에 이어서 작성

    //CoreDataPractice에서 데이터 Read
    func readAllData() {
        do {
            //PhoneBook+CoreDataProperties.swift의 fetchRequest()메소드를 사용해 fetch를 하면,
            //container안에 있는 모든 PhoneBook을 탐색
            let phoneBooks = try self.container.viewContext.fetch(PhoneBook.fetchRequest())
            
            //NSManagedObject로 타입캐스팅한 이유 : PhoneBook+CoreDataProperties.swift의 name, phoneNumber프로퍼티에 접근하기 위함
            for phoneBook in phoneBooks as [NSManagedObject] {
                if let name = phoneBook.value(forKey: PhoneBook.key.name) as? String,
                   let phoneNumber = phoneBook.value(forKey: PhoneBook.key.phoneNumber) as? String {
                    print("name: \(name), phoneNumber: \(phoneNumber)")
                }
            }
            
        } catch {
            print("데이터 읽기 실패")
        }
    }

4. Update

ViewController에 이어서 작성

    //CoreDataPractice에서 데이터 Update
    func updateData(currentName: String, updateName: String) {
        
        //데이터 조회
        let fetchRequest = PhoneBook.fetchRequest()
        
        //name이 currentName인 데이터를 찾음
        fetchRequest.predicate = NSPredicate(format: "name == %@", currentName)
        
        do {
            let result = try self.container.viewContext.fetch(fetchRequest)
            
            for data in result as [NSManagedObject] {
                
                // data 중 name의 값을 updateName으로 update한다
                data.setValue(updateName, forKey: PhoneBook.key.name)
            }
            
            //변조가 일어난 data를 저장
            try self.container.viewContext.save()
            print("데이터 수정 성공")
        } catch {
            print("데이터 수정 실패")
        }
    }

5. Delete

ViewController에 이어서 작성

    //CoreDataPractice에서 데이터 Delete
    func deleteData(name: String) {
        
        //데이터 조회
        let fetchRequest = PhoneBook.fetchRequest()
        
        //name이 같은 데이터를 찾음
        fetchRequest.predicate = NSPredicate(format: "name = %@", name)
        
        do {
            let result = try self.container.viewContext.fetch(fetchRequest)
            
            for data in result as [NSManagedObject] {
                self.container.viewContext.delete(data)
            }
            
            //변조가 일어난 data를 저장
            try self.container.viewContext.save()
            
            print("데이터 삭제 성공")
        } catch {
            print("데이터 삭제 실패")
        }
        
    }

0개의 댓글