[英]How to update @EnvironmentObject without button in SwiftUI?
我要在這里完成的是,當filterListGraph更新數據時,iconArray將添加數量,然后也更新數據。 我試圖使用.onAppear(),但是它沒有按我預期的那樣正常工作,因為它僅在GraphView出現時才添加一次(我需要從GraphView退出並返回以更新數據)。 可以在GraphView的iconArray中添加金額然后進行更新嗎?
struct IconStruct: Identifiable {
let id = UUID()
var icon: String
var amount: Double
var color: Color
var index: Int
}
class UserSettings: ObservableObject {
@Published var iconArray: [IconStruct] = [IconStruct(icon: "FoodIcon", amount: 0, color: Color(.red), index: 0),
IconStruct(icon: "ClothesIcon", amount: 0, color: Color(.blue), index: 1),
IconStruct(icon: "SportIcon", amount: 0, color: Color(.yellow), index: 2)]
}
struct GraphView: View {
var dateFormatter: DateFormatter {
let formatter = DateFormatter()
formatter.dateStyle = .long
return formatter
}
@EnvironmentObject var settings: UserSettings
@State private var fromDate = Calendar.current.date(byAdding: .month, value: -1, to: Date())!
@State private var toDate = Date()
@State private var selectedType = "type != %@"
@State private var selectedDate = true
@State private var searchText = ""
@State private var isNavigationBarHidden: Bool = true
var body: some View {
ScrollView {
VStack {
ForEach(settings.iconArray) { row in
Text(row.amount.description)
}
HStack {
Picker("", selection: $selectedType) {
Text("Expense").tag("type != %@")
Text("Income").tag("type == %@")
}
.pickerStyle(SegmentedPickerStyle())
}
HStack {
Picker("", selection: $selectedDate) {
Text("From: \(dateFormatter.string(from: fromDate))").tag(true)
Text("To: \(dateFormatter.string(from: toDate))").tag(false)
}
.pickerStyle(SegmentedPickerStyle())
}
DatePicker("", selection: selectedDate ? $fromDate : $toDate, displayedComponents: .date)
.labelsHidden()
}
PieChartRow(data: settings.iconArray, backgroundColor: .white)
.frame(width: 300, height: 300)
ForEach(settings.iconArray.sorted { $0.amount > $1.amount }) { icon in
filterListGraph(type: self.selectedType, icon: icon.icon, from: self.fromDate, to: self.toDate, iconIndex: icon.index)
}
}
}
}
struct filterListGraph: View {
@Environment(\.managedObjectContext) var context
var financeArray: FetchRequest<Finance>
var type: Bool
var icon: String
var iconIndex: Int
@EnvironmentObject var settings: UserSettings
var amount: Double {
return financeArray.wrappedValue.map { $0.wrappedAmount }.reduce(0,+)
}
// var amount: Double {
// self.settings.iconArray[self.iconIndex].amount = self.financeArray.wrappedValue.map { $0.wrappedAmount }.reduce(0,+)
// return self.settings.iconArray[self.iconIndex].amount
// }
var body: some View {
VStack {
if amount != 0 {
CellContainer(image: icon, label: nil, amount: amount.description, type: type)
}
// .onAppear() {
// self.settings.iconArray[self.iconIndex].amount = self.financeArray.wrappedValue.map { $0.wrappedAmount }.reduce(0,+)
// }
}
}
init(type: String, icon: String, from: Date, to: Date, iconIndex: Int) {
self.iconIndex = iconIndex
self.icon = icon
if type == "type == %@" {
self.type = true
} else {
self.type = false
}
financeArray = FetchRequest<Finance>(
entity: Finance.entity(),
sortDescriptors: [
NSSortDescriptor(keyPath: \Finance.date, ascending: true)
], predicate:
NSCompoundPredicate(notPredicateWithSubpredicate: NSCompoundPredicate.init(type: .or, subpredicates: [
NSPredicate(format: type, "false"),
NSPredicate(format: "icon != %@", icon),
NSPredicate(format: "date < %@ OR date >= %@", (Calendar.current.startOfDay(for: from) as NSDate), Calendar.current.date(byAdding: .day, value: 1, to: to)! as NSDate )
]))
)
}
}
如果我理解正確,則需要在UserSettings
跟蹤可變數量的數組。 我無法運行您的代碼,因為有一些空格,所以這里有一些技巧,希望它們對您有所幫助。 兩者都需要使用Combine
框架(您可以在此處閱讀有關內容)
UserSettings
創建可變數量 ,並在數組更改時更改它: import Combine
class UserSettings: ObservableObject {
@Published var amount: Double = 0.0
@Published var iconArray: [IconStruct] {
didSet {
self.amount = Double(iconArray.count)
}
}
init() {
self.iconArray = [IconStruct(icon: "FoodIcon", amount: 0, color: Color(.red), index: 0),
IconStruct(icon: "ClothesIcon", amount: 0, color: Color(.blue), index: 1),
IconStruct(icon: "SportIcon", amount: 0, color: Color(.yellow), index: 2)]
}
}
AnyPublisher
添加到設置中,然后對其進行訂閱: class UserSettings: ObservableObject {
@Published var amount: Double = 0.0
@Published var iconArray: [IconStruct] {
didSet {
self.amount = Double(iconArray.count)
}
}
var trackingAmount: AnyPublisher<Double, Never> {
return $amount
.eraseToAnyPublisher()
// or something else you need, read about Combine
}
init() {
self.iconArray = [IconStruct(icon: "FoodIcon", amount: 0, color: Color(.red), index: 0),
IconStruct(icon: "ClothesIcon", amount: 0, color: Color(.blue), index: 1),
IconStruct(icon: "SportIcon", amount: 0, color: Color(.yellow), index: 2)]
}
}
// here the key idea is .onReceive(settings.trackingAmount)
struct filterListGraph: View {
@EnvironmentObject var settings: UserSettings
var body: some View {
Text("some another view").onReceive(settings.trackingAmount) { _ in
// change what you need
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.