簡體   English   中英

如何在 SwiftUI 中檢索並在屏幕上顯示數據?

[英]How to retrieve and show data on screen in SwiftUI?

我將簡單數據存儲在我想要檢索並在屏幕上顯示的核心數據中,但我不確定我應該如何以及在哪里編寫該代碼以在屏幕上顯示它,因為我總是出現超出范圍的錯誤..

此外,並非所有數據都在時間保存,只有當我滾動到底部時才保存

import SwiftUI
import CoreData

struct ContentView: View {
    @Environment(\.managedObjectContext) private var viewContext

    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \Item.title, ascending: true)],
        animation: .default)
    private var items: FetchedResults<Item>

    @StateObject private var viewModel = HomeViewModel()
    

    var body: some View {
        GeometryReader { geometry in
            NavigationView {
                ScrollView {

                    LazyVGrid(columns: Array(repeating: .init(.flexible()),
                                             count: UIDevice.current.userInterfaceIdiom == .pad ? 4 : 2)) {
                        ForEach(viewModel.results, id: \.self) {
                            let viewModel = ResultVM(model: $0)
                            NavigationLink(destination: {
                                DetailView(data: viewModel.trackName)
                            }, label: {
                                SearchResultRow(resultVM: viewModel, coreDM: PersistenceController())
                            })
                        }
                    }
                }
            }
            .onAppear(perform: {
                viewModel.performSearch()
            })
        }
    }
}

struct SearchResultRow: View {

    let resultVM: ResultVM
    let coreDM: PersistenceController

    var body: some View {
        HStack {
            RoundedRectangle(cornerRadius: 16).fill(.yellow)
                .frame(maxWidth: .infinity).aspectRatio(1, contentMode: .fit)
                .overlay(Text(resultVM.trackName)) // want to show data from Core data here
        }.padding()
            .background(Color.red)
            .onAppear(perform: {
                coreDM.saveResult(title: resultVM.trackName)
            })
    }
}

來自 API 的數據顯示哪些相同的數據存儲在 CoreData

在此處輸入圖像描述

在此處輸入圖像描述

保存和檢索的方法(工作正常)

func saveResult(title: String) {
    let result =  Item(context: container.viewContext)
    result.title = title

    do {
        try container.viewContext.save()
    }
    catch {
        print("error")
    }
}

func getResult() -> [Item] {
    let fetchRequest: NSFetchRequest<Item> = Item.fetchRequest()

    do {
       return try container.viewContext.fetch(fetchRequest)
    }
    catch {
        return []
    }
}

API 調用

import Foundation
import CoreData

class HomeViewModel: ObservableObject {

    @Published var results = [ResultItem]()
    func performSearch() {
        guard let gUrl = URL(
            string: "https://api.artic.edu/api/v1/artworks"
        ) else { return }

        Task {
            do {
                let (data, _) = try await URLSession.shared.data(from: gUrl)
                let response = try JSONDecoder()
                    .decode(ResponseData.self, from: data)
                DispatchQueue.main.async { [weak self] in
                    self?.results = response.data ?? []
                }
            } catch {
                print("*** ERROR ***")
            }
        }
    }
}

刪除我們在 SwiftUI 中不使用視圖模型對象的視圖模型。 View結構存儲視圖數據並進行依賴跟蹤,屬性包裝器為其提供外部更改跟蹤功能,如對象。 如果您在頂部添加一個實際對象,您將獲得 SwiftUI 旨在消除的一致性錯誤。 所以首先刪除這個:

@StateObject private var viewModel = HomeViewModel()

您已經有了獲取請求屬性包裝器,正如我所說,它提供了View更改跟蹤,因此當items更改(例如,添加、刪除或移動項目)時,將調用body ,因此只需在ForEach中使用它即可這個:

ForEach(items) { item in
                        NavigationLink(destination: {
                            DetailView(item: item)
                        }, label: {
                            SearchResultRow(item: item)
                        })
                    }

然后在您的子視圖中使用@ObservedObject ,這使View能夠跟蹤項目的更改,因此當項目的屬性發生更改時將調用 body,例如item.title DetailView中執行相同的操作。

struct SearchResultRow: View {

    @ObservedObject var item: Item

在我看來,您正在嘗試在 Core Data 中下載和緩存數據。 這是不必要的,因為您可以簡單地在 NSURLSession 上設置一個 NSURLCache ,它會自動為您緩存它,即使離線也可以工作。 但是,如果你真的想自己在 Core Data 中緩存它,那么架構應該是你的 UI 從 Core Data 中獲取它,然后你有另一個對象負責將遠程數據同步到 Core Data 中。 通常這將在App結構級別而不是在出現的視圖中。 當數據保存到核心數據時,托管對象上下文上下文將被更改, @FetchRequest正在偵聽並調用body

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM