提问人:Ft klee 提问时间:10/17/2023 最后编辑:Ft klee 更新时间:10/18/2023 访问量:50
如何在 SwiftUI 中根据用户的选择获取特定数据?
How to fetch specific data based on user's choice in SwiftUI?
问:
我正在研究一种逻辑,用户可以选择标记他/她想在下一个学习会话中学习的卡片类别,但是,我目前面临的问题是我将如何根据选择获取数据。复选框的要点是让用户在点击“继续学习”按钮后按下他们想要学习的类别(或多个类别)。例如,用户可能会选择 1 和 2 类别,程序将重定向到 FlashcardSetView,并且显示的卡片将是用户之前选择的类别。此外,为了更清楚起见,以前,每张卡片都分配有一个(CoreData 属性)编号,该编号表示卡片所在的类别,以便以后用户能够研究他/她想要的卡片。FlashCardSetView
cardStatus
下面是 EndView(用户在其中选择接下来要研究的卡片类别):
import SwiftUI
struct EndView: View {
var set: FlashSets
@ObservedObject var dataController = DataController.shared
@State private var continueFlashying = false
@State private var returnHome = false
@State private var selectedCategories: [CategorySelection] = [
CategorySelection(category: 1, isSelected: false),
CategorySelection(category: 2, isSelected: false),
CategorySelection(category: 3, isSelected: false),
CategorySelection(category: 4, isSelected: false)
]
var selectedCardStatuses: [Int] {
return selectedCategories.filter { $0.isSelected }.map { $0.category }
}
var body: some View {
NavigationStack {
VStack {
Text("Set finished👍")
.bold()
.font(.system(size: 36))
.padding()
// Display the number of cards in each category
List {
ForEach(1...4, id: \.self) { category in
CategoryRow(categoryName: "Category \(category) cards studied: \(set.cardsArray.filter { $0.cardStatus == category }.count)", category: category, isSelected: $selectedCategories[category - 1].isSelected)
}
}
VStack {
Button(action: {
continueFlashying = true
}) {
Text("Continue studying")
NavigationLink(destination: FlashcardSetView(set: set, selectedCardStatuses: selectedCardStatuses), isActive: $continueFlashying) {
EmptyView()
}
}
Button(action: {
// Handle the "Start again" button
}) {
Text("Start again")
}
Button(action: {
returnHome = true
}) {
// Return home button
}
}
}
}
.navigationBarBackButtonHidden(true)
}}
struct CategoryRow: View {
let categoryName: String
let category: Int
@Binding var isSelected: Bool
var body: some View {
HStack {
Text(categoryName)
Spacer()
CheckboxView(isSelected: $isSelected)
}
}}
struct CheckboxView: View {
@Binding var isSelected: Bool
var body: some View {
Button(action: {
isSelected.toggle()
}) {
Image(systemName: isSelected ? "checkmark.circle.fill" : "circle")
.foregroundColor(isSelected ? .green : .secondary)
}
}}
struct CategorySelection {
var category: Int
var isSelected: Bool
}
下面是 FlashcardSetView:
struct FlashcardSetView: View {
// @FetchRequest(entity: FlashSets.entity(),
// sortDescriptors: [NSSortDescriptor(keyPath: \FlashSets.date, ascending: false)])
@FetchRequest(
entity: FlashCardData.entity(),
sortDescriptors: [NSSortDescriptor(keyPath: \FlashCardData.date, ascending: false)],
predicate: NSPredicate(format: "cardStatus == %d", 3) // Fetch cards with category 3
)
var categoryThreeCards: FetchedResults<FlashCardData>
var set: FlashSets
@ObservedObject var dataController = DataController.shared
@Environment(\.managedObjectContext) var managedObjectContext
@State private var showTermDefinitionView = false
@Environment(\.dismiss) var dismiss
@State private var isTapped = false
@State private var isEdited = false
//@State private var selectedCards: [FlashCardData] = [] // Keep track of selected cards
@State var allSwiped = false
@State private var showEndView = false
@State private var offset = CGSize.zero
@State private var currentlySelectedCard: FlashCardData?
@State var isLearned = false //1
@State var isThink = false //2
@State var isHard = false // 3
@State var isRepeat = false // 4
@State var studyPhase: StudyPhase = .initial
@State var currentCardIndex = 0
@State private var toEndView = false
var selectedCardStatuses: [Int]
var body: some View {
NavigationView {
ZStack {
NavigationLink(destination: EndView(set: set), isActive: $toEndView) {
EmptyView()
}
.isDetailLink(false)
Text("Card list is empty🙅♂️")
.padding(.top, -50)
if studyPhase == .initial {
ForEach(set.cardsArray, id: \.self) { card in
// if let unwrappedCard = card {
// //Text(unwrappedCard.name)
// }
VStack {
Text("Cards studied: \(currentCardIndex)")
.font(.headline)
.offset(y: -20)
SingleFlashCard(cards: set.cardsArray,
removal: {
withAnimation(.easeInOut) {
removeCurrentCard()
}
print("Removing card with animation")
}, set: set, currentCardIndex: $currentCardIndex, isLearned: $isLearned,
isThink: $isThink,
isHard: $isHard,
isRepeat: $isRepeat)
.offset(y: -20)
.transition(.asymmetric(insertion: .opacity, removal: .opacity))
}
.onAppear {
currentlySelectedCard = card
// Automatically transition to the EndView when all cards are studied
}
}
}
if studyPhase == .hard {
ForEach(categoryThreeCards, id: \.self) { card in
// if let unwrappedCard = card {
// //Text(unwrappedCard.name)
// }
VStack {
Text(set.cardsArray.count.description)
SingleFlashCard(cards: set.cardsArray,
removal: {
withAnimation(.easeInOut) {
removeCurrentCard()
}
print("Removing card with animation")
}, set: set, currentCardIndex: $currentCardIndex, isLearned: $isLearned,
isThink: $isThink,
isHard: $isHard,
isRepeat: $isRepeat)
.transition(.asymmetric(insertion: .opacity, removal: .opacity))
}
.onAppear {
currentlySelectedCard = card
}
}
}
NavigationLink(destination: EditFlashCardView(dataController: dataController, set: set), isActive: $isEdited) {
EmptyView()
}
.toolbar(.hidden, for: .tabBar)
}
}
.navigationBarBackButtonHidden(true)
.navigationBarItems(trailing:
Menu("Options") {
Button(action: {
showTermDefinitionView = true
}) {
NavigationLink(destination: TermDefinitionView(currentSet: set), isActive: $showTermDefinitionView) {
Text("Add cards")
}
}
Button(action: {
isEdited = true
}) {
Text("Edit cards")
}
}
)
HStack {
Button(action: {
currentlySelectedCard?.cardStatus = 1
//removeCard(currentlySelectedCard)
self.isLearned.toggle()
removeCurrentCard()
}) {
Text("👍")
.frame(width: 70, height: 50)
.background(Color("Easy"))
.clipShape(RoundedRectangle(cornerRadius: 8))
}
.padding(.trailing, 20)
Button(action: {
// Handle button action
self.isThink.toggle()
currentlySelectedCard?.cardStatus = 2
removeCurrentCard()
}) {
Text("🤔")
.frame(width: 70, height: 50)
.background(Color("Think"))
.clipShape(RoundedRectangle(cornerRadius: 8))
}
.padding(.trailing, 20)
Button(action: {
// Handle button action
self.isHard.toggle()
currentlySelectedCard?.cardStatus = 3
removeCurrentCard()
}) {
Text("🤬")
.frame(width: 70, height: 50)
.background(Color("Hard"))
.clipShape(RoundedRectangle(cornerRadius: 8))
}
.padding(.trailing, 20)
Button(action: {
// Handle button action
self.isRepeat.toggle()
currentlySelectedCard?.cardStatus = 4
removeCurrentCard()
}) {
Image(systemName: "repeat.circle.fill")
.frame(width: 70, height: 50)
.foregroundColor(.white)
.background(Color.red)
.clipShape(RoundedRectangle(cornerRadius: 8))
}
}
}
private func removeCurrentCard() {
if studyPhase == .initial {
if currentCardIndex < set.cardsArray.count - 1 {
currentCardIndex += 1 // Move to the next card
currentlySelectedCard = set.cardsArray[currentCardIndex] // Update currentlySelectedCard
} else {
if let lastCard = set.cardsArray.last {
// All cards in the set have been studied
toEndView = true // Transition to the EndView
} else {
studyPhase = .hard // Transition to the "hard" study phase if there are more cards
}
}
} else if studyPhase == .hard {
if currentCardIndex < categoryThreeCards.count - 1 {
currentCardIndex += 1 // Move to the next card
currentlySelectedCard = categoryThreeCards[currentCardIndex] // Update currentlySelectedCard
} else {
if categoryThreeCards.isEmpty {
// All "hard" cards are studied
toEndView = true // Transition to the EndView
} else {
// Handle the case when there are more cards in category 3
}
}
}
}
// func removeMethod(at index: Int) {
// set.cardsArray.remove(at: index)
// }
}
单抽认卡:
struct SingleFlashCard: View {
let cards: [FlashCardData]
var removal: (() -> Void)? = nil
var set: FlashSets
@State private var isTapped = false
@Binding var currentCardIndex: Int
@Binding var isLearned: Bool
@Binding var isThink: Bool
@Binding var isHard: Bool
@Binding var isRepeat: Bool
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 25, style: .continuous)
.fill(Color.white)
//.offset(x: isLearned ? 500 : 0)
//.overlay(RoundedRectangle(cornerRadius: 25).stroke(getColor(), lineWidth: 2))// Here we change the border color based on the swipe direction
.shadow(radius: 3)
VStack {
NavigationStack {
Text(currentCardIndex < set.cardsArray.count ? (set.cardsArray[currentCardIndex].term ?? "Unnamed Card") : "No more cards")
.offset(y: -100)
Divider()
if isTapped {
Text(currentCardIndex < set.cardsArray.count ? (set.cardsArray[currentCardIndex].definition ?? "Unnamed Card") : "No more cards")
.offset(y: 100)
}
}
}
}
.frame(width: 300, height: 500)
}
}
DataController 文件来控制 CoreData:
class DataController: ObservableObject {
static let shared = DataController()
@Published var termdefpairs: [TermAndDefinition] =
[TermAndDefinition(术语:“”,定义:“”)] @Published var savedFlash: [FlashCardData] = []
@Published var dataUpdated: Bool = false
let container: NSPersistentContainer
init(inMemory: Bool = false) {
container = NSPersistentContainer(name: "CoreData")
if inMemory {
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
}
// super.init()
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
self.container.viewContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
})
container.viewContext.automaticallyMergesChangesFromParent = true
//fetchRequest()
}
func addNew() {
termdefpairs.append(TermAndDefinition(term: "", definition: ""))
}
func fetchRequest() {
let request: NSFetchRequest<FlashCardData> = FlashCardData.fetchRequest()
let sort = NSSortDescriptor(keyPath: \FlashCardData.date, ascending: false)
request.sortDescriptors = [sort]
do {
self.savedFlash = try container.viewContext.fetch(request)
} catch {
print("Failed to fetch FlashCardData: \(error)")
}
}
func save() {
do {
try container.viewContext.save()
print("Data saved")
self.dataUpdated.toggle() // This will trigger the view to update
} catch {
print("We could not save the data...")
}
}
func add(term: String, definition: String, number: Int16, date: Date) {
let data = FlashCardData(context: self.container.viewContext)
data.id = UUID()
data.definition = definition
data.term = term
data.number = number
// data.tag = tag
data.date = date
// data.name = name
// fetchRequest()
}
func addFlashcardSet(name: String, tag: String, date: Date) {
let newSet = FlashSets(context: self.container.viewContext)
newSet.id = UUID()
newSet.name = name
newSet.tag = tag
newSet.date = Date()
}
func update(data: FlashCardData, term: String, defintion: String, date: Date, context: NSManagedObjectContext) {
data.term = term
data.definition = defintion
data.date = Date()
save()
}
func deleteFlashCard(data: FlashCardData) {
container.viewContext.delete(data)
save()
}
func updateFlashSet(set: FlashSets, name: String, tag: String, date: Date) {
set.name = name
set.tag = tag
set.date = date
save()
}
}
答: 暂无答案
评论