在这个视图中,如果我试图发送另一个视图,如CartItem(),那么应用程序会崩溃,并出现错误线程1:“对象已被删除或无效。”如果我再次进入应用程序,CartItem被删除!我认为对象是一些在使用中的地方
import Foundation
import RealmSwift
class ApiResponse: Decodable {
let status: Bool
let page: String
let category: String
let results: [Product]
}
class Product: Object, Identifiable, Decodable {
@Persisted var product_id: String
@Persisted var product_name: String
@Persisted var product_price: String
@Persisted var product_group: String
@Persisted var product_description: String
@Persisted var product_thumb_images: String
@Persisted var product_big_images: String
@Persisted var isInCart: Bool = false
// @Persisted var quantity: Int = 1 // Default quantity is 1
enum CodingKeys: String, CodingKey {
case product_id, product_name, product_price, product_group, product_description, product_thumb_images, product_big_images
}
override class func primaryKey() -> String? {
return "product_id"
}
}
class CartItem: Object,Identifiable {
@Persisted var product: Product?
@Persisted var quantity: Int = 1
convenience init(product: Product, quantity: Int) {
self.init()
self.product = product
self.quantity = quantity
}
}
import Foundation
import Alamofire
import SwiftUI
import RealmSwift
import Realm
class ProductViewModel: ObservableObject {
@Published var products: [Product]?
@Published var errorMessage: String?
@Published var cartItems: [CartItem] = []
@Published var selectedCategory: String = "All"
internal func fetch() {
let urlString: String
if selectedCategory == "All" {
urlString = ""
} else {
urlString = ""
}
guard let url = URL(string: urlString) else {
self.errorMessage = "Invalid URL"
return
}
AF.request(url)
.validate()
.responseDecodable(of: ApiResponse.self) { response in
switch response.result {
case .success(let apiResponse):
self.products = apiResponse.results
case .failure(let error):
self.errorMessage = "Error fetching data: \(error)"
}
}
}
func addToCart(product: Product) {
do {
let realm = try Realm()
if let existingProduct = realm.object(ofType: Product.self, forPrimaryKey: product.product_id) {
try realm.write {
if existingProduct.isInCart {
if let existingCartItem = cartItems.first(where: { $0.product?.product_id == product.product_id }) {
existingCartItem.quantity += 1
} else {
// Create a new CartItem with quantity 1
let cartItem = CartItem(product: existingProduct, quantity: 1)
realm.add(cartItem)
}
} else {
// Update the isInCart property and add to cart
existingProduct.isInCart = true
// Create a new CartItem with quantity 1
let cartItem = CartItem(product: existingProduct, quantity: 1)
realm.add(cartItem)
}
}
} else {
// Product does not exist in the database, handle accordingly
// Create a new CartItem with quantity 1
let cartItem = CartItem(product: product, quantity: 1)
try realm.write {
realm.add(cartItem)
}
}
updateCartItems()
} catch {
print("Error adding to cart: \(error)")
}
}
func removeFromCart(product: Product) {
do {
let realm = try Realm()
if let existingCartItem = cartItems.first(where: { $0.product?.product_id == product.product_id }) {
if existingCartItem.quantity > 1 {
try realm.write {
existingCartItem.quantity -= 1
}
} else {
// Update the isInCart property and remove from cart
if let existingProduct = existingCartItem.product {
try realm.write {
existingProduct.isInCart = false
}
}
try realm.write {
realm.delete(existingCartItem)
}
}
updateCartItems()
}
} catch {
print("Error removing from cart: \(error)")
}
}
internal func updateCartItems() {
do {
let realm = try Realm()
cartItems = Array(realm.objects(CartItem.self))
} catch {
print("Error updating cart items: \(error)")
}
}
func calculateTotalPrice() -> Double {
return cartItems.reduce(0) { $0 + Double($1.quantity) * Double($1.product?.product_price ?? "0")! }
}
}
//
// AddCartView.swift
// ZED_Shop
//
// Created by JARVIS on 22/12/23.
//
import SwiftUI
struct AddCartView: View {
@ObservedObject var viewModel: ProductViewModel
var body: some View {
NavigationView {
VStack {
if viewModel.cartItems.isEmpty {
Text("Your cart is empty.")
} else {
List {
ForEach(viewModel.cartItems) { cartItem in
VStack() {
HStack {
VStack{
Text(cartItem.product?.product_name ?? "Unknown Product")
.font(.smallCaps(.title3)())
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.top)
.padding(.leading)
Text("\(cartItem.product?.product_price ?? "0")")
.font(.title)
.fontWeight(.bold)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.leading)
.foregroundColor(.blue)
Text("\(cartItem.quantity)")
.foregroundColor(.black)
.padding(.bottom)
}
Spacer()
HStack{
RemoteImage(url: URL(string: cartItem.product!.product_thumb_images))
.frame(width: 130, height: 170)
}
}
}
}
.onDelete(perform: { indexSet in
viewModel.removeFromCart(product: viewModel.cartItems[indexSet.first!].product!)
})
}
}
Text("Total Price: \(viewModel.calculateTotalPrice())")
Button("Checkout") {
// Handle checkout logic
}
.disabled(viewModel.cartItems.isEmpty)
}
.navigationTitle("Cart")
.onAppear {
viewModel.updateCartItems() // Fetch cart items on appear
}
}
}
}
struct AddCartView_Previews: PreviewProvider {
static var previews: some View {
return AddCartView(viewModel: ProductViewModel())
}
}
import SwiftUI
import RealmSwift
struct CartItemView: View {
@ObservedObject var viewModel: ProductViewModel
let cartItem: CartItem
let product: Product
var body: some View {
HStack {
VStack(alignment: .leading) {
HStack {
Text(cartItem.product?.product_name ?? "Unknown Product")
.font(.smallCaps(.title3)())
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.top)
.padding(.leading)
Spacer()
Button(action: {
// Handle delete action
withAnimation {
viewModel.removeFromCart(product: cartItem.product!)
} }) {
Image(systemName: "trash")
.foregroundColor(.red)
}
.padding(.top)
.padding(.trailing)
.frame(width: 25, height: 25)
Spacer()
}
Text("₹\(String(format: "%.2f", viewModel.calculateTotalPrice()))")
.font(.title)
.fontWeight(.bold)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.leading)
.foregroundColor(.blue)
HStack {
Button(action: {
// Decrease quantity action
}) {
Text("-")
.frame(width: 50, height: 50)
.background(.blue.opacity(0.1))
.cornerRadius(10)
.foregroundColor(.black)
}
.padding(.bottom)
.padding(.leading, 20)
Spacer()
Text("\(cartItem.quantity)")
.foregroundColor(.black)
.padding(.bottom)
Spacer()
Button(action: {
// Increase quantity action
}) {
Text("+")
.frame(width: 50, height: 50)
.background(.blue.opacity(0.1))
.cornerRadius(10)
.foregroundColor(.black)
}
.padding(.bottom)
Spacer()
}
.frame(maxWidth: 200)
Spacer()
}
.frame(maxWidth: .infinity)
.frame(height: 170)
RemoteImage(url: URL(string: cartItem.product!.product_thumb_images))
.frame(width: 130, height: 170)
.frame(alignment: .trailing)
}
.frame(maxWidth: .infinity)
.frame(height: 170)
.background(Color.gray.opacity(0.1))
.cornerRadius(10)
.shadow(color: Color.black.opacity(0.1), radius: 5, x: 0, y: 2)
.padding(.leading)
.padding(.trailing)
}
}
字符串
请给予我解决这个问题的办法
我想在AddtoCartView中添加CartItem,如
struct AddCartView: View {
@ObservedObject var viewModel: ProductViewModel
var body: some View {
NavigationView {
VStack {
if viewModel.cartItems.isEmpty {
Text("Your cart is empty.")
} else {
List {
ForEach(viewModel.cartItems) { cartItem in
VStack() {
CartItemView(
viewModel:viewModel,
cartItem: cartItem, product: cartItem.product!
)
}
}
.onDelete(perform: { indexSet in
viewModel.removeFromCart(product: viewModel.cartItems[indexSet.first!].product!)
})
}
}
Text("Total Price: \(viewModel.calculateTotalPrice())")
Button("Checkout") {
// Handle checkout logic
}
.disabled(viewModel.cartItems.isEmpty)
}
.navigationTitle("Cart")
.onAppear {
viewModel.updateCartItems() // Fetch cart items on appear
}
}
}
}
struct AddCartView_Previews: PreviewProvider {
static var previews: some View {
return AddCartView(viewModel: ProductViewModel())
}
}
型
1条答案
按热度按时间4xrmg8kj1#
由于这是SwiftUI,你不应该有视图模型对象,这是视图结构层次的工作。状态应该分散在小的视图结构中,let用于只读或
@Binding
用于读/写,你不应该在每个视图中都有@ObservedObject
,这会使它慢下来,甚至可能是它崩溃的原因。尝试重命名并将ProductViewModel
拆分为ProductFetcher
/CartFetcher
,只包含fetch代码,并从中删除所有视图数据,例如像selectedCategory
。