relationship... 정말 헷갈리는 부분이지만
그만큼 CoreData에서 중요한 부분이기도 함!
코어데이터 설명 읽어보기!
마음 단단히 먹구!
코딩시작
뷰모델을 우선 선언해줌
촵
다음은 CoreData를 관리하는 객체를 싱글톤으로 만들어줄겨
이제 CoreData를 실제로 다뤄야하니까 import CoreData 해줬다
container랑 이 안에 존재하는 context를 상수로 선언해줌
초기값을 따로 안넣었으니까 init이 필요하겠죠
전이랑 다르게 context에 container.viewContext를 저장해주네
save 메소드도 하나 필요할 것 같음
아아 context.save()로 쉽게 쓸라고 한거구나
container.viewContext.save()를 조금 더 보기 쉽게할라고
CoreDataManager구성은 우선 마쳤고
viewModel로 돌아와서 방금 만든 매니저를 선언해주자
CoreDataContainer 라는 이름의 DataModel파일 작성!
3개의 entity를 만들어줄거임
BusinessEntity, DepartmentEntity, EmployeeEntity
이렇게 3가지
비즈니스 안에는 부서가 있을거고, 이 부서들 안에는 직원들이 있을 예정
비즈니스Entity에 name attribute를 구성하고,
부서Entity에 name attribute를 구성했다
두개를 연결해주자!
비즈니스Entity Relationships에departments라는 관계를 만들어줌
Destination은 관계의 방향에서 목적지, inverse는 어떤 관계랑 연결이 될지를 나타냄
Inspector창을 열면 Type항목이 있는데 하나로 대응될 지 여러개로 대응될지 정해줄 수 있음
원래는 하나의 비즈니스에선 여러개의 부서를 가지고
각각의 부서들은 그 상위의 비즈니스랑만 연결이 될텐데
지금 같은 경우엔 하나의 부서가 여러개의 비즈니스랑 대응될 수도 있을 거잖음
그래서 To Many로 골라줬음 (이건 개발자의 몫인거. 어떻게 관계를 맺을지는 온전히 나의 상황에 맞추면됨)
EmployeeEntity도 만들어줌! 나이랑 언제 출근시작했는지, 이름 같은 attribute를 만들어줬음
이번엔 이 직원들은 각각 하나 비즈니스랑 대응되는 관계 하나, 부서랑 대응되는 관계 하나로만 가능하게 해줬음
직원이 몸이 여러개도 아니고 출근을 여기저기 몸 담을 순 없잖음
비즈니스Entity에선 여러 갈래의 직원들이 있을거니까 many로 대응 되게 해줌
옼께이
부서도 마찬가지로 여러명의 직원들이 있을테니까 To Many로 대응되게 해줌
참 옛날처럼 editor모드 바꾸는 건 없어짐!
관계 설정끝!
다시 뷰모델 작성한 곳으로 돌아와서
@Published로 [BusinessEntity] 배열을 만들어줌
그리고 addBusiness 메소드를 구성해줄거임
manager에서 save로 context를 저장했던걸 다시 save()라는 메소드로 만들고
addBusiness에 추가해줌
간단한 뷰를 구성해주고
실행!
잘 실행됨
이제 저장된 Business Entity를 가져와봅시다
뷰모델에서 작성해준 getBusiness
struct BusinessView: View {
let entity: BusinessEntity
var body: some View {
VStack(alignment: .leading, spacing: 20) {
Text("Name: \(entity.name ?? "")")
.bold()
if let departments = entity.departments?.allObjects as? [DepartmentEntity] {
Text("Departments:")
.bold()
ForEach(departments) { department in
Text(department.name ?? "")
}
}
if let employees = entity.employees?.allObjects as? [EmployeeEntity] {
Text("Employees:")
.bold()
ForEach(employees) { employee in
Text(employee.name ?? "")
}
}
}
.padding()
.frame(maxWidth: 300, alignment: .leading)
.background(Color.gray.opacity(0.5))
.cornerRadius(10)
.shadow(radius: 10)
}
}
그리고 BusinessView를 구성해줬다
여서 보면 BusinessEntity안엔 departments랑 employees가 다 있음
entity.departments는 set라서 array로 바꿔주기 위해선 allObjects로 [Any]타입의 array를 만든 다음에 [DepartmentsEntyty] 타입으로 캐스팅해줘야함
employees도 마찬가지!
이제 만들어준 BusinessView를 원래의 뷰에서 horizontal ScrollView안에 ForEach로 돌려보자
save가 호출될 때 getBusinesses도 같이 호출되어야 뷰가 업뎃 됨
그리고 business가 add 될 때 departments랑 employees도 업뎃 되어야함
func addBusiness() {
let newBusiness = BusinessEntity(context: manager.context)
newBusiness.name = "Apple"
// add existing departments to the new business
//newBusiness.departments = []
// add existing employees to the new business
//newBusiness.employees = []
// add new business to existing department
//newBusiness.addToDepartments(<#T##value: DepartmentEntity##DepartmentEntity#>)
// add new business to existing employee
//newBusiness.addToEmployees(<#T##value: EmployeeEntity##EmployeeEntity#>)
save()
}
department를 추가해주는 메소드를 작성하고
기존에 cta Button로직을 vm.addDepartment로 바꿔줌
글고 지금 누적된거 지워줄라고 save될 때 기존의 businesses 안에 담긴 배열 싹 지우고
dispatchQueue.main.asyncAfter로 살짝 딜레이 줘서 save되게 해줌
DepartmentView도 만들었다!
BusinessView 그대로 복사하고
살짝 수정해줌
struct DepartmentView: View {
let entity: DepartmentEntity
var body: some View {
VStack(alignment: .leading, spacing: 20) {
Text("Name: \(entity.name ?? "")")
.bold()
if let businesses = entity.businesses?.allObjects as? [BusinessEntity] {
Text("Businesses:")
.bold()
ForEach(businesses) { business in
Text(business.name ?? "")
}
}
if let employees = entity.employees?.allObjects as? [EmployeeEntity] {
Text("Employees:")
.bold()
ForEach(employees) { employee in
Text(employee.name ?? "")
}
}
}
.padding()
.frame(maxWidth: 300, alignment: .leading)
.background(Color.green.opacity(0.5))
.cornerRadius(10)
.shadow(radius: 10)
}
}
bootcamp뷰에서
비즈니스 뷰 스크롤로 보이는 거 밑에
departments 뷰도 그려줄 거
vm 에 새로운 [DepartmentEntity] 배열이 필요하겠죠
구성해주고, getDepartments() 만들고 init 될 때 실행되게 해줌
save메소드에도 한번 removeall한 다음에 getDepartments로 업뎃 될 수 있게 해주고
새로운 Entity를 생성해주게 되면 Attribute말고도 relationship도 설정해줄 수 있다
기존에 있던 Entity에 추가해주는 것도 가능하고 새로운 Entity에 붙여주는 건 가능함
이제 Employee를 추가해봅시다
다른 business나 department 지정하지 않은채로 그냥 직원만 만드는 것도 가능함
sort 하는법
get할 때
fetchRequest를 할 때 sort 해주면 됨
filter는 predicate 추가하면되고
delet하는 과정에서 관계에 있는 다른 entity를 어떻게 처리할지 정해줄 수 있음
default는 nullify인데 다른 애는 남겨두는 형태로 지워짐
casacade는 관계에 있는 다른 entity도 다 지움
deny는 다른 관계의 entity가 존재한다면 안 지워짐