提问人:Nus 提问时间:11/9/2023 更新时间:11/10/2023 访问量:62
SwiftUI 列表视图返回错误类型“()”无法符合“使用核心数据查看”
SwiftUI List view return error Type '()' cannot conform to 'View with core data
问:
我已经实现了具有所需功能的核心数据。我正在尝试将函数调用到视图中,当我们没有数据进入核心数据时,这时我正在进行网络调用并将数据保存到核心数据中。我正在遵循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)
}
}
这是错误的屏幕截图..
答:
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)
上一个:iOS 中的文件关联
评论
coreData.saveProduct(products: product)
View