티스토리 뷰

iOS

Core Data (2)

Zedd0202 2020. 4. 8. 19:09
반응형

 

안녕하세요 :) Zedd입니다.

https://zeddios.tistory.com/987

 

Core Data (1)

안녕하세요 :) Zedd입니다. Core Data를 사용할 일이 생겼는데...제가 옜날에 해봤단 말이죠..!?!?!? 근데 다시 하려니까 생각이 하나도 안나는거에요 그때는 문서 볼 생각도 안했었는데..ㅎㅎㅎㅎ 이러면 할때마..

zeddios.tistory.com

저번 글에서 Core Data의 개념과 fetch, save방법을 알아보았습니다..!!!!

오늘은 NSManagedObjectContext의 여러 transaction 메소드들을 살펴볼거에요.

(transaction메소드라고 표현하는게 맞는지는 모르겠지만...) 

구구절절 설명안하고 딱 코드만 추가할 예정.

class PersistenceManager {
static var shared: PersistenceManager = PersistenceManager()
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "The name of the .xcdatamodeld file")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
var context: NSManagedObjectContext {
return self.persistentContainer.viewContext
}
}

PersistenceManager class하나를 만들었습니다.

저번 글에서는 AppDelegate.swift에서 persistentContainer를 가져왔지만,

이번엔 이 "Persistence"기능을 관장(?)하는 매니저 클래스를 하나 만들어봤어요.

그래서 이 친구가 persistentContainer도 가지고 있습니다. 

 

 

이 상태에서 메소드를 하나씩 추가해줄거에요. 최종 코드도 업로드 할게요~

 

- 저장된 데이터 fetch하는 법

class PersistenceManager {
static var shared: PersistenceManager = PersistenceManager()
..
func fetch<T: NSManagedObject>(request: NSFetchRequest<T>) -> [T] {
do {
let fetchResult = try self.context.fetch(request)
return fetchResult
} catch {
print(error.localizedDescription)
return []
}
}
}
let request: NSFetchRequest<Contact> = Contact.fetchRequest()
let fetchResult = PersistenceManager.shared.fetch(request: request) // [Contact]
view raw fetch.swift hosted with ❤ by GitHub

처음에는 fetchContact이런식으로 했다가..다들 각자의 NSManagedObject class타입이 있을거잖아요. (저같은 경우 Contact)

좀 general하게 쓰였으면 해서 generic을 사용해봤읍니다..

이렇게 할거면 persistentContainer의 파일 이름도 주입 받아야 하는데 걍 하겠음ㅎ

 

- 저장하는 법

아 근데 이건 setValue때문에...Contact..만을 위한 메소드가 필요하겠군요??!

class PersistenceManager {
static var shared: PersistenceManager = PersistenceManager()
..
@discardableResult
func insertPerson(person: Person) -> Bool {
let entity = NSEntityDescription.entity(forEntityName: "Contact", in: self.context)
if let entity = entity {
let managedObject = NSManagedObject(entity: entity, insertInto: self.context)
managedObject.setValue(person.name, forKey: "name")
managedObject.setValue(person.phoneNumber, forKey: "phoneNumber")
managedObject.setValue(person.shortcutNumber, forKey: "shortcutNumber")
do {
try self.context.save()
return true
} catch {
print(error.localizedDescription)
return false
}
} else {
return false
}
}
}
let walker = Person(name: "Walker", phoneNumber: "010-1234-5678", shortcutNumber: 2)
PersistenceManager.shared.insertPerson(person: walker)

ㅎㅎ...

 

- 특정 object삭제

class PersistenceManager {
static var shared: PersistenceManager = PersistenceManager()
...
@discardableResult
func delete(object: NSManagedObject) -> Bool {
self.context.delete(object)
do {
try context.save()
return true
} catch {
return false
}
}
}
let request: NSFetchRequest<Contact> = Contact.fetchRequest()
let fetchResult = PersistenceManager.shared.fetch(request: request)
PersistenceManager.shared.delete(object: fetchResult.last!)
view raw delete.swift hosted with ❤ by GitHub

 

- 전체 삭제

class PersistenceManager {
static var shared: PersistenceManager = PersistenceManager()
..
@discardableResult
func deleteAll<T: NSManagedObject>(request: NSFetchRequest<T>) -> Bool {
let request: NSFetchRequest<NSFetchRequestResult> = T.fetchRequest()
let delete = NSBatchDeleteRequest(fetchRequest: request)
do {
try self.context.execute(delete)
return true
} catch {
return false
}
}
}
let request: NSFetchRequest<Contact> = Contact.fetchRequest()
PersistenceManager.shared.deleteAll(request: request)
let arr = PersistenceManager.shared.fetch(request: request)
if arr.isEmpty {
print("clean") // Print "clean"
}
view raw deleteAll.swift hosted with ❤ by GitHub

 

- 갯수

fetch해서 받아온 결과 arr의 count를 사용해도 되지만,

cotext에 count가 있길래 한번 써보려구요~~

class PersistenceManager {
static var shared: PersistenceManager = PersistenceManager()
..
func count<T: NSManagedObject>(request: NSFetchRequest<T>) -> Int? {
do {
let count = try self.context.count(for: request)
return count
} catch {
return nil
}
}
}
let request: NSFetchRequest<Contact> = Contact.fetchRequest()
print(PersistenceManager.shared.count(request: request))
view raw count.swift hosted with ❤ by GitHub

 

- 배열 저장하기

이 부분은 댓글로 어떤분이 물어봐주셨는데 저도 궁금해서 해봅니다.

Entity에 배열로 만들고 싶은 Attribute를 만든뒤, 

이렇게요. 그 다음 오른쪽 inspector에서

Type을 Transformable로, custom Class에 내가 배열로 넣을 타입?을 지정해줍니다.

CoreDataProperties에

이것도 추가해줘야겠죠? 

그런 다음 똑같이 

setValue에 habbit도 추가해줍니다. 

그러면 저장이 잘 되는 걸 볼 수 있습니당!!!

 

나중에 추가되는 메소드 있으면 여기 추가해야지

 

 

아래는 전체 코드입니다. 

class PersistenceManager {
static var shared: PersistenceManager = PersistenceManager()
var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "Model")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
var context: NSManagedObjectContext {
return self.persistentContainer.viewContext
}
func fetch<T: NSManagedObject>(request: NSFetchRequest<T>) -> [T] {
do {
let fetchResult = try self.context.fetch(request)
return fetchResult
} catch {
print(error.localizedDescription)
return []
}
}
@discardableResult
func insertPerson(person: Person) -> Bool {
let entity = NSEntityDescription.entity(forEntityName: "Contact", in: self.context)
if let entity = entity {
let managedObject = NSManagedObject(entity: entity, insertInto: self.context)
managedObject.setValue(person.name, forKey: "name")
managedObject.setValue(person.phoneNumber, forKey: "phoneNumber")
managedObject.setValue(person.shortcutNumber, forKey: "shortcutNumber")
do {
try self.context.save()
return true
} catch {
print(error.localizedDescription)
return false
}
} else {
return false
}
}
@discardableResult
func delete(object: NSManagedObject) -> Bool {
self.context.delete(object)
do{
try self.context.save()
return true
} catch {
return false
}
}
func count<T: NSManagedObject>(request: NSFetchRequest<T>) -> Int? {
do {
let count = try self.context.count(for: request)
return count
} catch {
return nil
}
}
@discardableResult
func deleteAll<T: NSManagedObject>(request: NSFetchRequest<T>) -> Bool {
let request: NSFetchRequest<NSFetchRequestResult> = T.fetchRequest()
let delete = NSBatchDeleteRequest(fetchRequest: request)
do {
try self.context.execute(delete)
return true
} catch {
print(error.localizedDescription)
return false
}
}
}

 

저 iOS 진짜 아예 처음 할 때 Persistence기능을 썼어야 했거든요zzzz

근데 그때 막 하나도 모르는데 Core Data가 있대...

근데 그땐 Swift도 아예 모를 때라 (for문도 모름ㅋ) 진짜 멘붕

Realm이 쉽다던데.. -> 뭐 쓰기 쉽다고..? 그래 Realm 쓰자 -> 딱 이 의식의 흐름

 

예전에 Core Data 썼을 때는 그냥 공부 안하고 막 가져다가 썼어서...ㅎㅎㅎㅎㅎ

근데 Core Data도 차근차근 공부하니까 쉽네요 ~.~

도움이 되었길 바랍니다!

 

 

반응형

'iOS' 카테고리의 다른 글

iOS ) UICollectionReusableView  (2) 2020.04.11
RxTest  (2) 2020.04.09
Core Data (1)  (6) 2020.03.31
iOS ) CATextLayer  (0) 2020.02.24
iOS ) CAGradientLayer  (0) 2020.02.02