提问人:Tessa Limbeek 提问时间:11/16/2023 更新时间:11/17/2023 访问量:64
“删除”按钮生成“不允许从视图更新中发布更改,这将导致未定义的行为。
Delete button produces "Publishing changes from within view updates is not allowed, this will cause undefined behavior."
问:
我有一个来自数据库的买家列表,当点击删除按钮时,我收到名称错误的警报按钮,并在“买家”上出现以下错误:
“不允许从视图更新中发布更改,这将导致未定义的行为。”
这是我的 BuyersView,我在其中显示买家列表
struct BuyersView: View {
@StateObject var viewModel = BuyersViewModel()
@State var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
VStack{
CategoryView(categories: viewModel.fases, currentSelection: $viewModel.currentFase)
HStack{
Spacer()
NavigationLink("Add buyer", value: 0)
.padding()
}
List(viewModel.buyers){ buyer in
// refactor this later to a separate view
HStack{
NavigationLink(value: buyer) {
VStack(alignment: .leading){
Text(buyer.name ?? "name")
.font(.title3)
Text("Fase : \(buyer.fase ?? "fase")")
}
}
Spacer()
DeleteButton(showingAlert: $viewModel.showingAlert, buyer: buyer, vm: viewModel, deleteUser: {viewModel.deleteBuyer(id: buyer.id, currentfase: viewModel.currentFase)})
}
}.onChange(of: viewModel.currentFase) { _, newValue in
viewModel.resetBuyers()
}
}
.navigationDestination(for: Int.self) { _ in
AddBuyerView(path: $path, fases: viewModel.fases, onBuyerAdded: { viewModel.resetBuyers()})
}.navigationDestination(for: BuyerData.self) { buyer in
BuyerDetailView(buyer: buyer)
}
}
}
}
这是我的 BuyerViewModel
import Foundation
class BuyersViewModel: ObservableObject {
@Published var buyers : [BuyerData] = []
@Published var showingAlert = false
@Published var currentFase : Category = .init(title: "All Buyers")
let fases: [Category] = [
.init(title: "All Buyers"),
.init(title: "Nieuw"),
.init(title: "Email contact"),
.init(title: "Gesproken"),
.init(title: "Gepland"),
.init(title: "Bezocht"),
.init(title: "Bod"),
.init(title: "Sale"),
.init(title: "Zoekt niet meer")
]
init() {
buyers = getAllBuyers(currentfase: currentFase)
}
func deleteBuyer(id: Int, currentfase: Category) {
let db = DBHelper()
db.deleteBuyer(id: id)
if currentfase.title == "All Buyers"{
buyers = db.AllBuyers()
}
else{
buyers = db.AllB(fase: currentfase.title)
}
db.close()
}
func getAllBuyers(currentfase: Category) -> [BuyerData]{
let db = DBHelper()
var allbuyers: [BuyerData]
if currentfase.title == "All Buyers"{
allbuyers = db.AllBuyers()
}
else{
allbuyers = db.AllB(fase: currentfase.title)
}
db.close()
return allbuyers
}
func resetBuyers(){
buyers = getAllBuyers(currentfase: currentFase)
}
}
这是我对删除按钮本身的看法
struct DeleteButton: View {
@Binding var showingAlert : Bool
var buyer : BuyerData?
var seller: SellerData?
@StateObject var vm : BuyersViewModel
var deleteUser: () -> Void
var messageText : String {
(seller == nil ? buyer?.name : seller?.name) ?? "this user"
}
var titleText : String {
buyer == nil ? "Seller" : "Buyer"
}
var body: some View {
Button("delete") {
vm.showingAlert = true
}
.buttonStyle(.borderless)
.foregroundColor(.red)
.alert("Deleting \(titleText)", isPresented: $showingAlert) {
Button(role: .destructive) {
//vm.deleteBuyer(id: buyer.id, currentfase: vm.currentFase)
deleteUser()
vm.showingAlert = false
} label: {
Text("Delete")
}
Button(role: .cancel) {
vm.showingAlert = false
} label: {
Text("Cancel")
}
} message: {
Text("Are you sure you want to delete \(messageText) \n this action cannot be undone")
}
}
}
为什么我会收到这个错误,我该如何解决这个问题?
答:
0赞
Guillermo Jiménez
11/16/2023
#1
你在 和 之间是多余的,你可以只是。DeleteButton
BuyersViewModel
编辑:
- 下次请添加 M个初始的、可重复的例子
- 这是修复程序,因此通过在 中添加标志,错误是每个视图都试图同时打开相同的视图
ViewModel
Alert
列表视图
import SwiftUI
struct BuyersView: View {
@StateObject var viewModel = BuyersViewModel()
@State var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
VStack{
//CategoryView(categories: viewModel.fases, currentSelection: $viewModel.currentFase)
HStack{
Spacer()
NavigationLink("Add buyer", value: 0)
.padding()
}
List($viewModel.buyers){ $buyer in
// refactor this later to a separate view
NavigationLink(value: buyer) {
HStack{
VStack(alignment: .leading){
Text(buyer.name)// ?? "name")
.font(.title3)
Text("Fase : \(buyer.fase ?? "fase")")
}
Spacer()
DeleteButton(buyer: buyer, vm: viewModel)
}
}
}
.onChange(of: viewModel.currentFase) { _, newValue in
viewModel.resetBuyers()
}
}
.navigationDestination(for: Int.self) { _ in
// AddBuyerView(path: $path, fases: viewModel.fases, onBuyerAdded: { viewModel.resetBuyers()})
}.navigationDestination(for: BuyerData.self) { buyer in
// BuyerDetailView(buyer: buyer)
}
}
}
}
视图模型
import Foundation
struct BuyerData: Identifiable, Hashable {
let id: Int
let name: String
let fase: String = "All Buyers"
}
struct Category: Equatable {
let title: String
}
class BuyersViewModel: ObservableObject {
@Published var buyers : [BuyerData] = []
@Published var currentFase : Category = .init(title: "All Buyers")
let fases: [Category] = [
.init(title: "All Buyers"),
.init(title: "Nieuw"),
.init(title: "Email contact"),
.init(title: "Gesproken"),
.init(title: "Gepland"),
.init(title: "Bezocht"),
.init(title: "Bod"),
.init(title: "Sale"),
.init(title: "Zoekt niet meer")
]
init() {
buyers = getAllBuyers(currentfase: currentFase)
}
func deleteBuyer(id: Int) {
print(id)
if let index = buyers.firstIndex(where: {$0.id == id}) {
buyers.remove(at: index)
}
}
func getAllBuyers(currentfase: Category) -> [BuyerData] {
var allbuyers: [BuyerData] = [
BuyerData(id: 1, name: "Buyer number 1"),
BuyerData(id: 2, name: "Buyer number 2"),
BuyerData(id: 3, name: "Buyer number 3"),
BuyerData(id: 4, name: "Buyer number 4")
]
return allbuyers
}
func resetBuyers(){
buyers = getAllBuyers(currentfase: currentFase)
}
}
按钮
import SwiftUI
struct DeleteButton: View {
var buyer : BuyerData?
@ObservedObject var vm : BuyersViewModel
@State private var showingAlert = false
var messageText : String {
"this user"
}
var titleText : String {
buyer == nil ? "Seller" : "Buyer"
}
var body: some View {
Button("delete") {
showingAlert = true
}
.buttonStyle(.borderless)
.foregroundColor(.red)
.alert("Deleting \(titleText)", isPresented: $showingAlert) {
Button(role: .destructive) {
if let buyer {
vm.deleteBuyer(id: buyer.id)
showingAlert = false
}
} label: {
Text("Delete")
}
Button(role: .cancel) {
showingAlert = false
} label: {
Text("Cancel")
}
} message: {
Text("Are you sure you want to delete \(messageText) \n this action cannot be undone")
}
}
}
让 ViewModel 按应有的方式处理所有逻辑,无论您使用数据库,删除和刷新数据的逻辑都是相同的。
评论
0赞
Tessa Limbeek
11/16/2023
我更改了它,但我仍然收到相同的错误,并且它想要删除错误的买家
评论