關于以下專案:
您的金額為 100 當您單擊一個用戶的“加號”按鈕時,該特定用戶必須支付此金額,但如果您單擊多個用戶的“加號”按鈕,支付的金額將在他們之間平均分配。
當我單擊“加號”按鈕時,知道如何更新整個 Model2.MustPayM2 道具嗎?
import SwiftUI
struct Model1: Identifiable, Codable {
var id: String = UUID().uuidString
var nameM1: String
var amountM1: Double
var amountSumM1: Double = 100
var arrayM2: [Model2]
var isVisible: Bool = false
}
struct Model2: Identifiable, Codable {
var id: String = UUID().uuidString
var nameM2: String
var amountM2: Double = 0
var mustPayM2: Bool = false
}
class ViewModel1: ObservableObject {
@Published var Publi1: Model1
@Published var Publi1s: [Model1] = []
@Published var Publi2: Model2
@Published var Publi2s: [Model2] = []
init() {
let pub2 = Model2(nameM2: "init")
let pub1 = Model1(nameM1: "init", amountM1: 0, arrayM2: [pub2])
self.Publi2 = pub2
self.Publi1 = pub1
var newPub1s: [Model1] = []
for i in (0..<5) {
let newNameM1 = "name\(i 1)"
let newAmountM1 = Double(i 1)
var newModel1 = Model1(nameM1: newNameM1, amountM1: newAmountM1, arrayM2: [pub2])
var newPub2s: [Model2] = []
for i in (0..<5) {
let newNameM2 = "\(newNameM1)-user\(i 1)"
let newModel2 = Model2(nameM2: newNameM2)
newPub2s.append(newModel2)
}
newModel1.arrayM2 = newPub2s
newPub1s.append(newModel1)
}
Publi1s = newPub1s
Publi1 = newPub1s[0]
Publi2s = newPub1s[0].arrayM2
Publi2 = newPub1s[0].arrayM2[0]
}
}
struct View1: View {
@EnvironmentObject var VM1: ViewModel1
@State private var tt: String = ""
private let screenHeight = UIScreen.main.bounds.height
var body: some View {
ZStack {
VStack {
ForEach(0..<VM1.Publi2s.count, id: \.self) { i in
Text("\(VM1.Publi2s[i].nameM2)")
Text(tt)
Button {
VM1.Publi2s[i].mustPayM2.toggle()
var a = VM1.Publi2s.filter { $0.mustPayM2 == true }
let b = VM1.Publi1.amountM1 / Double(a.count)
// How can I update the new props between all users ??
// for j in 0..<a.count {
// a[j].amountM2 = b
// }
} label: {
Image(systemName: "plus")
}
}
Spacer()
Button {
VM1.Publi1.isVisible.toggle()
} label: {
Text("SHOW ME")
}
Spacer()
}
View2()
.offset(y: VM1.Publi1.isVisible ? 0 : screenHeight)
}
}
}
struct View2: View {
@EnvironmentObject var VM1: ViewModel1
var body: some View {
VStack {
Spacer()
ForEach(0..<VM1.Publi2s.count, id: \.self) { i in
Text("\(VM1.Publi2s[i].amountM2)")
}
}
}
}
struct View2_Previews: PreviewProvider {
static var previews: some View {
Group {
View1()
}
.environmentObject(ViewModel1())
}
}
uj5u.com熱心網友回復:
您的實作似乎過于復雜且容易出錯。我實際上為此重寫了代碼。我添加了評論,以明確我做了什么以及為什么做了某些事情。如果你不明白為什么,不要猶豫,問一個問題。但請先閱讀并嘗試理解代碼。
//Create one Model containing the individuals
struct Person: Identifiable, Codable{
var id = UUID()
var name: String
var amountToPay: Double = 0.0
var shouldPay: Bool = false
}
//Create one Viewmodel
class Viewmodel:ObservableObject{
//Entities being observed by the View
@Published var persons: [Person] = []
init(){
//Create data
persons = (0...4).map { index in
Person(name: "name \(index)")
}
}
//Function that can be called by the View to toggle the state
func togglePersonPay(with id: UUID){
let index = persons.firstIndex { $0.id == id}
guard let index = index else {
return
}
//Assign new value. This will trigger the UI to update
persons[index].shouldPay.toggle()
}
//Function to calculate the individual ammount that should be paid and assign it
func calculatePayment(for ammount: Double){
//Get all persons wich should pay
let personsToPay = persons.filter { $0.shouldPay }
//Calcualte the individual ammount
let individualAmount = ammount / Double(personsToPay.count)
//and assign it. This implementation will trigger the UI only once to update
persons = persons.map { person in
var person = person
person.amountToPay = person.shouldPay ? individualAmount : 0
return person
}
}
}
struct PersonView: View{
//pull the viewmodel from the environment
@EnvironmentObject private var viewmodel: Viewmodel
//The Entity that holds the individual data
var person: Person
var body: some View{
VStack{
HStack{
Text(person.name)
Text("\(person.amountToPay, specifier: "%.2f")$")
}
Button{
//toggle the state
viewmodel.togglePersonPay(with: person.id)
} label: {
//Assign label depending on person state
Image(systemName: "\(person.shouldPay ? "minus" : "plus")")
}
}
}
}
struct ContentView: View{
//Create and observe the viewmodel
@StateObject private var viewmodel = Viewmodel()
var body: some View{
VStack{
//Create loop to display person.
//Dont′t itterate over the indices this is bad practice
// itterate over the items themselves
ForEach(viewmodel.persons){ person in
PersonView(person: person )
.environmentObject(viewmodel)
.padding(10)
}
Button{
//call the func to calculate the result
viewmodel.calculatePayment(for: 100)
}label: {
Text("SHOW ME")
}
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/479065.html
標籤:IOS 循环 迅捷 可观察对象 swiftui-foreach
