본문 바로가기

iOS

[iOS] 8주차) Coredata

서버를 안쓰고 프로젝트를 구현하는 방식은 몇가지 있는데, 

 

1) Coredata

2) UserDefault

3) SQLite

 

오늘은 Coredata를 이용해서 내부DB를 사용해볼 것입니다!

Coredata는 iOS 10 이상의, 특정 템플릿에서 Coredata를 지원합니다. 이 중 SingleView App은 Coredata를 지원하니,

이를 이용해서 실습을 해보겠습니다.

 

실습은 https://www.raywenderlich.com/7569-getting-started-with-core-data-tutorial 을 통해서 했는데,

코드 구현은 간단한 테이블 뷰로 되어 있습니닷

오역이 있다면 말씀해 주십쇼

 

 

 

Coredata를 선택하면, 오른쪽과 같이 Xcdatamodeld이라는 확장자를 가진 파일이 생성됩니다.

얘를 누르면 원래는 아무것도 없을텐데, 하단부의 Add Entities를 누르면 Entity를 생성할 수 있고,

Entity가 가질 Attribute를 설정해주십쇼

 

아래와 같이 설정해 보았고, 그림은 예제와 다릅니다! ✅예제 : entity 이름 : person, attribute 이름 : name  

또한, Coredata를 사용하기 전에는

import Coredata

를 해 주어야 함니다

 

코어데이터를 사용할 때 해야 할 필수적인 몇가지가 있는데

AppDelegate의 managedObjectContext와, xcdatamodeld,

NSManagedObject와 NSPersistentContainer ✅가 있습니다. 

NSManagedObject

A base class that implements the behavior required of a Core Data model object. 

Coredata의 모든 데이터의 생성, 제거, 수정을 하기 위해서 해당 객체를 사용해야만 합니다. 임의의 entity를 나타낼 수 있습니다.

NSPersistentContainer

A container that encapsulates the CoreData stack in your app. 

이 컨테이너를 통해 NSManagedObject 객체들을 다룰 수 있게 합니다. 프로젝트를 만들 때 Use Core Data를 선택하면 

AppDelegate에  아래와 같이 선언이 됩니다. 

 

하지만, 프로젝트 중간에 Coredata를 사용하게 된다면, AppDelegate에 아래와 같이 선언해주어야 합니다.

 lazy var persistentContainer: NSPersistentContainer = {
    
    let container = NSPersistentContainer(name: "HitList")  // name은 entity의 이름
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
      if let error = error as NSError? {
   
        fatalError("Unresolved error \(error), \(error.userInfo)")
      }
    })
    return container
  }()

 


 

 

코어데이터를 사용하고자 하는 곳에, 빈 NSManagedObject를 선언해 주어야 합니다.

해당 방법과 같이 Coredata 내부 데이터를 다룰 수 있습니다.

var models: [NSManagedObject] = [NSManagedObject]()
let name: String = models.first?.value(forKey: "name") as? String

*Key Value Coding : KVC에 대한 언급!* 

NSManagedObject는 name attribute를 알 수 없고, 따라서 attribute를 직접 가져올 수 없어서,

Key Value Coding을 통해서만 값을 읽을 수 있습니다.  

 

 

 

다음은 코드 리뷰입니다!

 

저장하는 함수 save입니다. 이 함수가 실행되면 내부DB에 String이 저장됩니다. 

func save(name: String) {

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

  // 1
  let managedContext =
    appDelegate.persistentContainer.viewContext

  // 2
  let entity =
    NSEntityDescription.entity(forEntityName: "Person",
                               in: managedContext)!

  let person = NSManagedObject(entity: entity,
                               insertInto: managedContext)

  // 3
  person.setValue(name, forKeyPath: "name")

  // 4
  do {
    try managedContext.save()
    people.append(person)
  } catch let error as NSError {
    print("Could not save. \(error), \(error.userInfo)")
  }
}

설명 : entity 이름 : person, attribute 이름 : name 

 

1. Delegate 선언을 통해, persistentContainer를 받아옵니다. viewContext는 persistentContainer의 ReadOnly 변수입니다.

 

ManagedObjectContext를 선언하여 managed object를 담아놓습니다.

이를 'Commit' 해야 디스크에 저장이 됩니다.

 

2. NSManagedObject를 이용하여 Coredata 내부의 entity를 받아옵니다. 

 

3. NSManagedObject를 2번에서 얻었으니, key-value coding을 사용해 name attribute를 설정합니다.

반드시 KVC 키(이 경우에는 name)이 Data Model 에 있는것과 일치해야 합니다.

 

4. managedContext.save()는 반드시 do - catch 문에서 이뤄져야 합니다. save는 에러가 발생할 수 있기 때문입니다.

 

다음은, 디비에서 fetch를 해 옵시다.

 override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

	// 1
    guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
      return
    }

	// 2
    let managedContext = appDelegate.persistentContainer.viewContext
    let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Person")

	// 3
    do {
      people = try managedContext.fetch(fetchRequest)
    } catch let error as NSError {
      print("Could not fetch. \(error), \(error.userInfo)")
    }
  }

fetch라고 해서 다르지 않습니다!

과정이 비슷한데,

 

1. appDelegate 선언,

2. managedContext를 선언 ( ManagedObjectContext )

fetchRequest : 기준을 충족하는 객체 집합을 가져오는 강력하고 유연한 함수.

 

3. 역시나 fetch도 에러가 날 수 있기 때문에 do - catch문에서 사용.

 

실행 화면 

앱을 껐다가 켜도, 테이블뷰에 데이터가 살아있는 모습을 볼 수 있슴니다!

 

 

 

entity, attribute를 다뤘으나 entity간의 relationship을 다루지 않았음! 

image를 포함한 Coredata실습을 할것임! 생각한건 요즘 유행하고있는 설문조사? 심리테스트? 를 하려 해씀!

만들어서 오게습니다

 

 

 

 

 

 

 

 

'iOS' 카테고리의 다른 글

[iOS] Calendar (1)  (0) 2020.04.25
[iOS] LinkPresentation  (0) 2020.04.18
[iOS, Crecker] ActionSheet,  (0) 2020.04.11
[Crecker, iOS] PageViewController (android : ViewPager)  (2) 2020.04.04
[Crecker,iOS] Swift ViewPager 구성  (4) 2020.03.28