SwiftUI 列表视图返回错误类型“()”无法符合“使用核心数据查看”

SwiftUI List view return error Type '()' cannot conform to 'View with core data

提问人:Nus 提问时间:11/9/2023 更新时间:11/10/2023 访问量:62

问:

我已经实现了具有所需功能的核心数据。我正在尝试将函数调用到视图中,当我们没有数据进入核心数据时,这时我正在进行网络调用并将数据保存到核心数据中。我正在遵循MVVM架构模式。在视图中,我也有搜索功能。问题是当我尝试调用保存函数时,我收到以下错误。

类型“()”不能符合“视图”

我期望当我们进行网络调用时,它应该将数据配置到列表中,并将其保存到核心数据存储中。

这是核心数据功能。

import Foundation
import CoreData

class CoreDataViewModel: ObservableObject {

    let persistentContainer: NSPersistentContainer

    init() {
        persistentContainer = NSPersistentContainer(name: "ProductDataManager")
        persistentContainer.loadPersistentStores { (description, error) in
            if let error = error {
                print("Core Data Store failed \(error.localizedDescription)")
            }
        }
    }
func saveProduct(products: Product) {

        let product = ProductEntity(context: persistentContainer.viewContext)
        product.id = Int16(products.id)
        product.title = products.title
        product.price = Int32(products.price)
        product.quantity = Int16(products.quantity)
        product.total = Int32(products.total)
        product.discountPercentage = products.discountPercentage
        product.discountedPrice = Int32(products.discountedPrice)

        do {
            try persistentContainer.viewContext.save()
        } catch {
            print("Failed to save movie \(error)")
        }
    }
}

这是我的观点 模型代码..如果需要,它依赖于 ProductRepository,我也可以添加该代码。

import Foundation

protocol ProductListViewModelAction: ObservableObject {
    func getProductList(urlStr: String) async
}

@MainActor
final class ProductListViewModel {
    
    @Published private(set) var productLists: [Product] = []
    @Published private var filteredProductLists: [Product] = []
    @Published private(set) var customError: NetworkError?
    
    private let repository: ProductRepository
    init(repository: ProductRepository) {
        self.repository = repository
    }
}

extension ProductListViewModel: ProductListViewModelAction {
    func getProductList(urlStr: String) async {

        guard let url = URL(string: urlStr) else {
        self.customError = NetworkError.invalidURL
        return
        }
        do {
            let lists = try await repository.getList(for: url)
            productLists = lists.carts.first?.products ?? []
            
        } catch {
            customError = error as? NetworkError
        }
    }
}

extension ProductListViewModel {
    
    func performSearch(keyword: String) {
        filteredProductLists = self.productLists.filter {
            $0.title.localizedCaseInsensitiveContains(keyword)
        }
    }
    var productList: [Product] {
        filteredProductLists.isEmpty ? productLists: filteredProductLists
    }
}

这是我的观点代码..

import SwiftUI

struct ProductListView: View {
    
    @StateObject var viewModel = ProductListViewModel(repository: ProductRepositoryImplementation(networkManager: NetworkManager()))

    @StateObject var coreData = CoreDataViewModel()
    @State var searchText = ""

     var body: some View  {

        NavigationStack {
            VStack {
                    if viewModel.productLists.count > 0 {

                        List(viewModel.productList, id: \.self) { product in
                            NavigationLink(destination: ProductDetailsView(product: product)) {
                                ProductListViewCell(productData: product)
                                coreData.saveProduct(products: product) // error is here ..
                            }

                        } .listStyle(.grouped)
                    }
                }
            }
            .searchable(text: $searchText)
            .onChange(of: searchText, perform: viewModel.performSearch)
            .navigationTitle(Text("Product List"))
        }.task {
            await getDataFromAPI()
        }
        .refreshable {
            await getDataFromAPI()
        }
    }
      func getDataFromAPI() async {
        await viewModel.getProductList(urlStr: NetworkURL.productUrl)
    }
}

这是错误的屏幕截图..

enter image description here

iOS Swift ListView SwiftUI 核心数据

评论

0赞 workingdog support Ukraine 11/9/2023
你得到的错误是因为你有一些过程代码,你只能有一个.再次阅读 SwiftUI 的基础知识并做一些教程,例如 SwiftUIcoreData.saveProduct(products: product)View
1赞 lorem ipsum 11/9/2023
使用 onAppear 或正文呈现的任务

答:

1赞 Dris 11/10/2023 #1

当有人开始使用 SwiftUI 时,这是一个常见的错误:试图调用只允许视图类型的函数。

您可以通过在视图出现时调用函数来轻松解决此问题:

List(viewModel.productList, id: \.self) { product in
    NavigationLink(destination: ProductDetailsView(product: product)) {
           ProductListViewCell(productData: product)
               .onAppear {
                  coreData.saveProduct(products: product)
               }
           }
}

但是,由于列表的行为,在滚动视图时,它可能会多次出现。我会检查它是否已经保存,以防止不必要的保存操作。

请注意:产品有一个“id”变量,因此您可以使其符合可识别协议。之后,无需在 List 或 ForEach 中指定“id”。

List(viewModel.productList)