斯威夫特用户界面。如何访问/操作视图之间的数据
Posted
技术标签:
【中文标题】斯威夫特用户界面。如何访问/操作视图之间的数据【英文标题】:SwiftUI. How do I access/manipulate data between views 【发布时间】:2020-10-02 21:27:51 【问题描述】:这段代码不是我的专用代码,但它会更清楚地显示我遇到的问题。它是费用计算应用程序的一部分。在视图之间传输数据后,我很难处理数据。我有 2 个视图,我想把所有的费用加起来。部分问题是我每次添加新的“费用”时都会创建一个类的新实例。
import SwiftUI
struct AddView: View
@Environment(\.presentationMode) var presentationMode
@ObservedObject var expenses: Expenses
@State private var name = ""
@State private var type = "Personal"
@State private var amount = ""
static let types = ["Business", "Personal"]
var body: some View
NavigationView
Form
TextField("Name", text: $name)
Picker("Type", selection: $type)
ForEach(Self.types, id: \.self)
Text($0)
TextField("Amount", text: $amount)
.keyboardType(.numberPad)
.navigationBarTitle("Add new expense")
.navigationBarItems(trailing: Button("Save")
if let actualAmount = Int(self.amount)
let item = ExpenseItem(name: self.name, type: self.type, amount: actualAmount)
self.expenses.items.append(item)
self.presentationMode
.wrappedValue.dismiss()
)
//第二视图
import SwiftUI
struct ExpenseItem: Identifiable, Codable
let id = UUID()
let name: String
let type: String
let amount: Int
class Expenses: ObservableObject
@Published var items = [ExpenseItem]()
didSet
let encoder = JSONEncoder()
if let encoded = try?
encoder.encode(items)
UserDefaults.standard.set(encoded, forKey: "Items")
init()
if let items = UserDefaults.standard.data(forKey: "Items")
let decoder = JSONDecoder()
if let decoded = try?
decoder.decode([ExpenseItem].self, from: items)
self.items = decoded
return
struct ContentView: View
@ObservedObject var expenses = Expenses()
@State private var showingAddExpense = false
var body: some View
NavigationView
List
ForEach(expenses.items) item in
HStack
VStack
Text(item.name)
.font(.headline)
Text(item.type)
Spacer()
Text("$\(item.amount)")
.onDelete(perform: removeItems)
.navigationBarTitle("iExpense")
.navigationBarItems(trailing: Button(action:
self.showingAddExpense = true
)
Image(systemName: "plus")
)
.sheet(isPresented: $showingAddExpense)
AddView(expenses: self.expenses)
func removeItems(at offsets: IndexSet)
expenses.items.remove(atOffsets: offsets)
struct ContentView_Previews: PreviewProvider
static var previews: some View
ContentView()
【问题讨论】:
听起来代码是别人写的,但是你能分享你自己定制的部分吗?不幸的是,如果没有一些代码示例,将很难确定问题所在。 我很抱歉。我不小心提交了帖子而没有附加我的代码!这段代码来自“HackingWithSwift”,是他的“iExpenses”SwiftUI 教程。我的应用程序基于它。重申一下,我正在尝试计算费用金额并将所有条目加在一起。希望这可以帮助。谢谢! 【参考方案1】:这真的取决于你想在哪里显示总数。最简单的解决方案是在ContentView
的所有费用列表之后显示总计。
但首先我们需要计算总数。由于总数与我们的Expenses
ObservableObject
相关,因此它计算它是自己的总数是有道理的。
Expenses
类只有一个实例,它包含ExpenseItem
结构的多个实例。我们将通过向Expenses
类添加一个计算属性来解决这个问题。我已从您的示例中删除了一些代码,以突出显示我所做的更改。
class Expenses: ObservableObject
@Published var items: [ExpenseItem]
// ...
// Computed property that calculates the total amount
var total: Int
self.items.reduce(0) result, item -> Int in
result + item.amount
计算的属性总计将所有ExpenseItem
数量减少为一个值。您可以阅读有关 reduce here 的更多信息,也可以阅读有关计算属性 here 的信息。我们不必使用reduce,我们可以使用for循环并对值求和。我们也不必使用计算属性,我们可以使用函数。这真的取决于你想要什么。
接下来在ContentView
中,我们可以向List
添加一个显示总数的视图。
struct ContentView: View
@ObservedObject var expenses = Expenses()
@State private var showingAddExpense = false
var body: some View
NavigationView
List
ForEach(expenses.items) item in
// ...
.onDelete(perform: removeItems)
// View that shows the total amount of the expenses
HStack
Text("Total")
Spacer()
Text("\(expenses.total)")
// ...
// ...
这将为您提供如下所示的结果。
【讨论】:
就是这样!感谢您的回答,您的解释非常好!以上是关于斯威夫特用户界面。如何访问/操作视图之间的数据的主要内容,如果未能解决你的问题,请参考以下文章
如何将 JSON 令牌保存到用户默认值,然后在不同的视图中使用它?斯威夫特 4
如何将 UIScrollView 移动一帧的宽度? (Xcode,斯威夫特)