Although Xcode does not give me any information, I assumed that it is related to Core Data because it started since I changed codes related to Core Data.
My Code
I have many codes in my project, and I cannot show you the whole code because of word limit. But I can show the core of my project.
ContentView - includes two tab views(VocabularyFolderView and QuizHome View)
import SwiftUI
struct ContentView: View {
var body: some View {
TabView {
VocabularyFolderView()
.tabItem {
Label("Vocabulary", systemImage: "list.dash")
}
QuizHomeView()
.tabItem {
Label("Quiz", systemImage: "questionmark.app")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
//ForEach(["iPhone SE (3nd generation)", "iPhone 13", "iPad Pro (11-inch) (1st generation)", "iPad Air (3rd generation)", "iPad Air (4th generation)"], id: \.self) { deviceName in
//ContentView()
//.environment(\.managedObjectContext, PersistenceController.VocabularyFolder_Preview.container.viewContext)
//.previewDevice(PreviewDevice(rawValue: deviceName))
//.previewDisplayName(deviceName)
//}
ContentView()
.environment(\.managedObjectContext, PersistenceController.VocabularyFolder_Preview.container.viewContext)
.previewInterfaceOrientation(.portrait)
}
}
VocabularyFolderView - It is a NavigationView that contains a list of Core Data entities
import SwiftUI
import CoreData
struct VocabularyFolderView: View {
@Environment(\.managedObjectContext) private var managedObjectContext
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \FolderStruct.name, ascending: true)],
animation: .default)
private var folders: FetchedResults<FolderStruct>
@State private var showAddView: Bool = false
@State private var showAddErrorAlert: Bool = false
@State private var showDeleteErrorAlert: Bool = false
@State private var showFavoritesOnly = false
var filteredFolders: [FolderStruct] {
folders.filter { folder in
(!showFavoritesOnly || folder.starred)
}
}
var body: some View {
NavigationView {
List {
Section {
Toggle(isOn: $showFavoritesOnly) {
Text("Favorites only")
}
}
Section {
ForEach(filteredFolders) { folder in
NavigationLink {
VocabularyListView(parentFolder: folder)
} label: {
HStack {
Image(systemName: "folder")
.foregroundColor(.accentColor)
.listRowSeparator(.hidden)
Text(folder.name ?? "")
Spacer()
Text("\(folder.childlists!.count)")
.foregroundColor(.secondary)
if folder.starred {
Image(systemName: "star.fill")
.foregroundColor(.yellow)
} else {
Image(systemName: "star")
.foregroundColor(.gray)
}
}
}
.swipeActions(edge: .leading) {
Button {
deleteFolder(folder: folder)
} label: {
Label("Pin", systemImage: "pin.fill")
}
.tint(.orange)
}
.swipeActions(edge:. trailing, allowsFullSwipe: false) {
Button(role: .destructive) {
deleteFolder(folder: folder)
} label: {
Label("Delete", systemImage: "trash.fill")
}
}
}
}
}
.navigationTitle("Folders")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
EditButton()
}
ToolbarItem(placement: .bottomBar) {
HStack {
Button(action: addItem) {
Label("Add Item", systemImage: "folder.badge.plus")
}
Spacer()
}
}
}
.sheet(isPresented: $showAddView) {
AddFolderView()
}
//alert(isPresented: $showAddView,
// TextAlert(title: "New Folder", message: "Message") { result in
// if let text = result {
// // Text was accepted
// } else {
// // The dialog was cancelled
// }
// })
.alert("Error while deleting a word", isPresented: $showDeleteErrorAlert) {
Button("OK", role: .cancel) { }
}
.alert("Error while adding a word", isPresented: $showAddErrorAlert) {
Button("OK", role: .cancel) { }
}
}
.navigationViewStyle(StackNavigationViewStyle())
}
private func addItem() {
showAddView = true
}
private func deleteFolder(folder: FolderStruct) {
managedObjectContext.delete(folder)
do {
try managedObjectContext.save()
} catch {
showDeleteErrorAlert = true
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}
struct VocabularyFolderView_Previews: PreviewProvider {
static var previews: some View {
VocabularyFolderView().environment(\.managedObjectContext, PersistenceController.VocabularyFolder_Preview.container.viewContext)
}
}
QuizHomeView
import SwiftUI
import CoreData
struct QuizHomeView: View {
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \FolderStruct.name, ascending: true)],
animation: .default)
private var folders: FetchedResults<FolderStruct>
@State private var showingSheet = false
@State private var quizType = "단어 뜻 맞추기"
@State private var folderSelection: FolderStruct?
@State private var listSelection = "단어장 선택"
let quizTypes = ["단어 뜻 맞추기", "원래 단어 맞추기"]
var body: some View {
NavigationView {
Form {
Section {
Picker("Quiz Type", selection: $quizType) {
ForEach(quizTypes, id: \.self) {
Text($0)
}
}
.pickerStyle(.segmented)
}
Section {
Picker("폴더 선택", selection: $folderSelection) {
ForEach(folders) { (folder: FolderStruct) in
Text(folder.name!)
}
}
//Picker("단어장 선택", selection: $listSelection) {
// ForEach(listSelections, id: \.self) {
// Text($0)
// }
//}
}
Section {
Button("시작하기") {
showingSheet.toggle()
}
.disabled(folderSelection == nil || listSelection.isEmpty || listSelection == "단어장 선택")
}
}
.navigationTitle("퀴즈")
.sheet(isPresented: $showingSheet) {
QuizPlayView()
}
}
}
}
struct QuizHomeView_Previews: PreviewProvider {
static var previews: some View {
QuizHomeView()
}
}
Persistence.swift
import CoreData
import Foundation
struct PersistenceController {
static let shared = PersistenceController()
static var VocabularyFolder_Preview: PersistenceController = {
let result = PersistenceController(inMemory: true)
let viewContext = result.container.viewContext
var previewString = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
for i in previewString {
let newFolder = FolderStruct(context: viewContext)
newFolder.name = i
newFolder.starred = true
}
do {
try viewContext.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
return result
}()
static var AddFolder_Preview: PersistenceController = {
let result = PersistenceController(inMemory: true)
let viewContext = result.container.viewContext
let newFolder = FolderStruct(context: viewContext)
newFolder.name = "Example Folder"
newFolder.starred = true
do {
try viewContext.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
return result
}()
static var VocabularyList_Preview: PersistenceController = {
let result = PersistenceController(inMemory: true)
let viewContext = result.container.viewContext
var previewString = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
for i in previewString {
let parentFolder = FolderStruct(context: viewContext)
parentFolder.name = i
parentFolder.starred = true
let newList = ListStruct(context: viewContext)
newList.name = i
newList.starred = true
newList.parentfolder = parentFolder
}
do {
try viewContext.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
return result
}()
static var AddList_Preview: PersistenceController = {
let result = PersistenceController(inMemory: true)
let viewContext = result.container.viewContext
let parentFolder = FolderStruct(context: viewContext)
parentFolder.name = "Example Folder"
parentFolder.starred = true
let newList = ListStruct(context: viewContext)
newList.name = "Example List"
newList.starred = true
newList.parentfolder = parentFolder
do {
try viewContext.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
return result
}()
static var Vocabulary_Preview: PersistenceController = {
let result = PersistenceController(inMemory: true)
let viewContext = result.container.viewContext
let previewString = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
for i in previewString {
let parentList = ListStruct(context: viewContext)
parentList.name = i
parentList.starred = true
let newVocabulary = VocabularyStruct(context: viewContext)
newVocabulary.word = i
newVocabulary.meaning = i
newVocabulary.starred = true
newVocabulary.parentlist = parentList
}
do {
try viewContext.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
return result
}()
static var AddVocabulary_Preview: PersistenceController = {
let result = PersistenceController(inMemory: true)
let viewContext = result.container.viewContext
let parentList = ListStruct(context: viewContext)
parentList.name = "Example List"
parentList.starred = true
let newVocabulary = VocabularyStruct(context: viewContext)
newVocabulary.word = "Example Word"
newVocabulary.meaning = "Example Meaning"
newVocabulary.starred = true
newVocabulary.parentlist = parentList
do {
try viewContext.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
return result
}()
static var FolderStruct_Preview: FolderStruct {
let folder = FolderStruct()
folder.name = "Example Folder"
folder.starred = true
return folder
}
static var ListStruct_Preview: ListStruct {
let list = ListStruct()
list.name = "Example List"
list.starred = true
list.parentfolder = FolderStruct_Preview
return list
}
static var VocabularyStruct_Preview: VocabularyStruct {
let vocabulary = VocabularyStruct()
vocabulary.word = "Example Word"
vocabulary.meaning = "Example Meaning"
vocabulary.starred = true
vocabulary.parentlist = ListStruct_Preview
return vocabulary
}
let container: NSPersistentCloudKitContainer
init(inMemory: Bool = false) {
container = NSPersistentCloudKitContainer(name: "Vocabulary")
if inMemory {
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
}
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
container.viewContext.automaticallyMergesChangesFromParent = true
}
}