我正在使用 swiftUI 制作一个简单的新闻应用程序,问题是我想将视图模型添加到我的项目中,但现在当我运行该应用程序时,视图上没有显示任何内容,但在我添加视图模型之前,一切都很完美,现在我有了视图模型,我想由于某种原因它看不到更改或无法通信。我尝试了我能想到的一切,所以我需要一些帮助。
应用入口
@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()
}
}
}
当更改发生时,我想在应用程序的视图上显示它,但没有任何内容被放入视图中
结构不太正确,异步函数必须返回一些东西,并且在 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()
}
}
}