DEV_Larva
GaNaDa - MemoPage 본문
가나다 앱에서는 자신이 학습한 내용을 메모해둘 수 있도록 메모 페이지를 따로 추가해뒀는데, 크게 나를 힘들게 했던 건 아녔었기 때문에 별생각 없이 지나갔나 했지만, 최근 다시 보니 메모해두려고 추가해놓은 메모 리스트들이 앱을 종료 후 다시 재접속을 하면 초기화가 되어있는 것부터 UI, UX 측면에서 상당히 거슬리는 부분이 한두 가지가 아니었다. 그래서 결국은 아예 새로 갈아엎어버리기로 했다. 기존에 있던 것에서 몇 가지를 바꿔 보았지만, 기본적인 View 자체의 설계부터 다시 해보고 싶었다. 그러기 위해 학습해야 했던 내용은 데이터를 영구 저장하기 위한 방법을 조사해보았다.
1. iOS 에서 데이터 저장 방법
기본적으로 iOS에서 데이터를 저장하는 방법에는 UseDefaults를 사용하거나, Core Data를 사용하는 방법 총 두 가지가 대표적이었다. 각각 간단히 알아보자.
1. UseDefaults : 앱 실행 시 지속적으로 키-값 쌍을 저장하는 사용자의 기본 데이터베이스에 대한 인터페이스로 주로 사용자 기본 설정과 같이 단일 데이터 값에 사용하는 것이 적절하다고 한다. 쉽게 이해하자면 iPhone의 기본 설정이나, 게임 앱의 기본 설정에 대한 데이터 값을 UseDefaults를 사용하여 저장할 수 있다고 생각하면 될 것 같다. 더 자세한 내용은 아래 공식 문서의 링크를 통해 확인해보자.
https://developer.apple.com/documentation/foundation/userdefaults
Apple Developer Documentation
developer.apple.com
2. Core Data : 장치에서 데이터를 유지 또는 캐시 하거나 CloudKit을 사용해 여러 장치에 동기화 하는것을 말한다. Core Data는 데이터를 정렬하고 필터링할 수 있으며 훨씬 더 큰 데이터로 작업할 수 있다. 저장할 수 있는 데이터의 양에는 사실상 제한이 없다. 그리고 UseDefaults보다 더 좋은 점은 Core Data는 데이터 유효성 검사, 데이터 지연 로드, 실행 취소 및 다시 실행 등 필요한 경우를 위해 모든 종류의 고급 기능을 구현한다는 것이다. 자세한 내용은 아래 링크에서 확인해보도록 하자.
https://developer.apple.com/documentation/coredata
Apple Developer Documentation
developer.apple.com
2. Core Data 사용하기
나의 경우 해당 메모 페이지를 Core Data로 구현 하기로 하였는데, 이 과정을 찬찬히 한번 알아보자.
가장 먼저 새로운 파일을 하나 만들어 줘야한다. 여기서는 데이터 모델 파일을 만들어 주게 된다. 파일명은 자신이 원하는 대로 하면 된다.
그리고 이 파일을 한번 열어보면 좌측아래 Add Entity라는 버튼이 있을 텐데 이를 눌러주면 엔티티를 추가할 수 있고 그럼 해당 엔티티의 속성을 추가할 수 있게 되는 것이다. 나의 경우 Data라는 이름의 엔티티를 만들어 주었고, 그 내부에 메모장에 쓸 단어, 단어의 의미, 이후 난이도를 설정할 때 필요한 평가도를 추가해보았다. 각각의 타입은 자신의 데이터 타입에 맞게 설정해주면 된다.
3. MainView
해당 뷰에서는 말 그대로 사용자가 추가해놓은 메모(단어) 리스트들을 나열하여 출력하기 위해 필요한 뷰이다. 여기서 가장 먼저 작업을 시작하기 전에 추가 해놓아야 하는 것이 있는데, 가장 먼저 단어 리스트를 수정할 때 사용할 수 있는 관리 개체 콘텍스트, 보유한 모든 단어를 읽어오는 것을 요청하기 위한 도구, 추가 화면이 표시되는지에 대한 여부를 물어보기 위한 부울을 표현해야 한다. 이 세 가지 속성을 코드화 시켜 보면 다음과 같다.
@Environment(\.managedObjectContext) var moc
@FetchRequest(sortDescriptors: []) var books: FetchedResults<Book>
@State private var showingAddScreen = false
여기서 showingAddScreen이 이후에 새로운 단어를 추가할려고 추가 버튼을 누를 때 추가 화면을 표시할지 말지를 결정해준다고 보면 된다.
var body: some View {
NavigationView {
List {
ForEach(datas) { Data in
HStack {
RatingDetailView(rate: Data.rate)
.font(.largeTitle)
VStack {
Text(Data.word ?? "Unknown word")
.font(.headline)
Text(Data.mean ?? "Unknown word")
.foregroundColor(.secondary)
}
}
}.onDelete(perform: deleteBooks) //리스트 삭제
}
.navigationTitle("Vocabulary")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button { //메모 추가 버튼
showingAddScreen.toggle()
} label: {
Label("Add Word", systemImage: "plus")
}
}
}
.sheet(isPresented: $showingAddScreen) { //추가 화면을 AddWordView로
AddWordView()
}
}
}
4. 새로운 단어 추가
위에서 언급하였던 AddWordView가 바로 여기다. 여기서는 메인에서 보여줄 메모 리스트를 해당 뷰에서 사용자로 부터 입력받아 메인에서 나열하는 방식으로 개발하였다.
메인과 동일 하게 AddWordView에서도 속성 측면에서 관리 개체 콘텍스트를 저장하기 위해서는 환경 속성이 필요하다. 두 번째에 있는 dissmiss()의 경우 현재 보고 있는 view를 닫을 수 있게 하기 위해 추가한 환경 속성이라고 할 수 있다.
@Environment(\.managedObjectContext) var moc
@Environment(\.dismiss) var dismiss
그리고 메모장을 구성하는데 필요한 데이터들의 각 값에 대한 @State 속성을 추가해주었다. 나의 경우 아까 엔티티 내부의 속성 값을 그대로 사용하였다.
@State private var word = ""
@State private var mean = ""
@State private var rate = 0
이후에 작성할 body 부분의 경우 자신이 원하는 대로 개발해보면 될 것이기 때문에 굳이 나의 코드와 똑같이 할 필요는 없다.
NavigationView {
Form {
Section {
TextField("Type the Word",text: $word)
TextField("Type the Meaning",text: $mean)
}
Section {
RatingView(rate: $rate)
} header: {
Text("Rate difficulty")
}
Section {
Button("Save") {
let newWord = Data(context: moc)
newWord.word = word
newWord.mean = mean
newWord.rate = Int16(rate)
try? moc.save()
dismiss()
}
}
}.navigationTitle("Add Word")
}
}
}
struct AddWordView_Previews: PreviewProvider {
static var previews: some View {
AddWordView()
}
}
기본적으로 알고 있는 NavigationView에 Form, Section을 이용하여 사용자로부터 새로운 단어를 입력받을 수 있도록 하였다. 이렇게만 본다면 Core Data를 사용한다고 해서 코드가 엄청 달라지지는 않는다. 기존의 코드에서 데이터 모델의 속성 값을 읽어 오기 위해서 코드 앞부분에 환경 속성을 추가해주는 것, 그것이 이번 시간에 중점적으로 봐야 하는 부분이다.
글을 작성하다 보니 생각보다 글이 길어질 거 같아 다음 페이지부터는 다음 글에서 작성을 해볼 예정이다. 일단은 끝!👍
'iOS > 개인 프로젝트' 카테고리의 다른 글
GaNaDa - TabView (0) | 2022.12.27 |
---|---|
GaNaDa - MemoPage(2) (0) | 2022.12.04 |
GaNaDa - Onboarding (0) | 2022.11.25 |
GaNaDa 2번째 (0) | 2022.11.10 |
GaNaDa 시작 (0) | 2022.10.29 |