对我的模型/视图模型的更改不会对我视图上的内容进行收费

问题描述 投票:0回答:1

我正在使用 swiftUI 制作一个简单的新闻应用程序,问题是我想将视图模型添加到我的项目中,但现在当我运行该应用程序时,视图上没有显示任何内容,但在我添加视图模型之前,一切都很完美,现在我有了视图模型,我想由于某种原因它看不到更改或无法通信。我尝试了我能想到的一切,所以我需要一些帮助。

What shows when I run the app

应用入口

@main
struct GameNewsApp: App {
    
    @State var newsModel = NewsViewModel()
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(newsModel)
        }
    }
}

型号

struct ArticleSearch: Decodable {
        var results = [Articles]()
}
struct Articles: Decodable, Identifiable {
    let id = UUID()
    var publish_date: String?
    var authors: String?
    var title: String?
    var image: Images?
    var deck: String?
    var body: String?
    var categories: [Category]
}

struct Images: Decodable {
    var square_tiny: String?
    var screen_tiny: String?
    var square_small: String?
    var original: String?
}

struct Category: Decodable, Identifiable {
    var id: Int?
    var name: String?
}

观点

struct ContentView: View {
    var body: some View {
        
        TabView {
            NewsView()
                .tabItem {
                    Label("Game News", systemImage: "gamecontroller")
                }
            
            VideoView()
                .tabItem {
                    Label("Game Videos", systemImage: "airplayvideo")
                }
        }
        .onAppear {
            UITabBar.appearance().scrollEdgeAppearance = UITabBarAppearance()
        }
        .preferredColorScheme(.dark)
    }
}

#Preview {
    ContentView()
}
struct NewsView: View {
    
    @Environment (NewsViewModel.self) var newsModel
    
    var body: some View {
        NavigationStack {
            ScrollView(showsIndicators: false) {
                VStack {
                    ForEach(newsModel.articles) { a in
                        NavigationLink {
                            DetailNews()
                        } label: {
                            NewsCard()
                        }
                        .onTapGesture {
                            newsModel.selectedNews = a
                        }
                    }
                }
            }
            .navigationTitle("Game News")
        }
        .onAppear {
            newsModel.getNewsData()
        }
        .refreshable {
            newsModel.getNewsData()
        }
    }
}

#Preview {
    NewsView()
}
import SwiftUI
import CachedAsyncImage

struct NewsCard: View {
    
    @Environment(NewsViewModel.self) var newsModel
    
    var body: some View {
        
        let articles = newsModel.selectedNews
        
        VStack(alignment: .leading, spacing: 0) {
            CachedAsyncImage(url: URL(string: articles?.image?.original ?? "")) { image in
                switch image {
                case .empty:
                    HStack {
                        Spacer()
                        ProgressView()
                        Spacer()
                    }
                case .success(let image):
                    image
                        .resizable()
                        .clipShape(.rect(topLeadingRadius: 10, topTrailingRadius: 10))
                        .frame(height: 150)
                        .padding(.bottom, 10)
                        .overlay {
                            LinearGradient(stops: [
                                Gradient.Stop(color: .clear, location: 0.6),
                                Gradient.Stop(color: .black, location: 1)
                            ], startPoint: .top, endPoint: .bottom)
                        }
                case .failure:
                    HStack {
                        Spacer()
                        Image(systemName: "photo")
                            .imageScale(.large)
                        Spacer()
                    }
                @unknown default:
                    fatalError()
                }
            }
            .frame(maxHeight: 150)
            .background(Color.gray.opacity(0.3))
            .clipped()
            
            
                Spacer()

                Text(articles?.title ?? "")
                    .font(.title3)
                    .fontWeight(.bold)
                    .lineLimit(3)
                    .padding(.bottom, 10)
                    .padding(.horizontal)
                    .multilineTextAlignment(.leading)
            
                Text(articles?.deck ?? "")
                    .font(.subheadline)
                    .lineLimit(4)
                    .padding(.bottom, 10)
                    .padding(.horizontal)
                    .multilineTextAlignment(.leading)
            
            Spacer()
            
            HStack {
                ForEach(articles?.categories ?? []) { category in
                    Text(category.name ?? "")
                }
            }
            .padding(.horizontal)
            .padding(.bottom, 5)
            
                Spacer()
            
            }
            .frame(height: 350)
            .overlay {
                RoundedRectangle(cornerRadius: 10)
                    .stroke(.white)
            }
            .padding(.all, 10)
            .foregroundStyle(.white)
    }
}


#Preview {
    NewsCard()
}

查看模型

@Observable
class NewsViewModel {
    
    var articles = [Articles]()
    var dataService = DataService()
    var selectedNews: Articles?
    
    func getNewsData() {
        Task {
            articles = await dataService.articleSearch()
        }
    }
}

当更改发生时,我想在应用程序的视图上显示它,但没有任何内容被放入视图中

swift swiftui view viewmodel
1个回答
0
投票

结构不太正确,异步函数必须返回一些东西,并且在 SwiftUI 中它是

.task
而不是
Task{}
以获得正确的生命周期,请尝试这样的事情:

struct DataService {
    // background thread
    func articleSearch() async -> [News]{
        return ...
    }
}

struct NewsView: View {
    
    @Environment(\.dataService) var dataService // have to learn EnvironmentKey
    @State var articles: [Articles] = []

    var body: some View {
        List(articles) { article in
            ...
        }
        .task {
            articles = await dataService.articleSearch()
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.