简体   繁体   English

如何将数据从 SwiftUI 中的 ContentView 传递到子视图

[英]How to pass data to a sub view from ContentView in SwiftUI

Forgive me if this doesn't make sense, I am a total beginner at Swift.如果这没有意义,请原谅我,我是 Swift 的初学者。 I am creating a recipe app that pulls data from an API and lists it out in navigation links.我正在创建一个配方应用程序,它从 API 中提取数据并将其列在导航链接中。 When the user clicks on the recipe I want it to move to sub view and display information from the API such as recipe name, image, ingredients, and have a button with a link to the webpage.当用户单击食谱时,我希望它移动到子视图并显示来自 API 的信息,例如食谱名称、图像、成分,并有一个带有网页链接的按钮。

I was able to get the data pulled into the list with navigation links.我能够通过导航链接将数据拉入列表。 However, now I do not know how to go about setting up the recipe details sub view with all of the information I listed above.但是,现在我不知道如何使用我上面列出的所有信息设置配方详细信息子视图。

This is where I call the API:这就是我称之为 API 的地方:


class RecipeService {
    func getRecipes(_ completion: @escaping (Result<[Recipe], Error>) -> ()) {
        let url = URL(string: "http://www.recipepuppy.com/api")!
        URLSession.shared.dataTask(with: url) { (data, _, error) in
            
            if let error = error {
                return completion(.failure(error))
            }
            
            guard let data = data else {
                return completion(.failure(NSError(domain: "", code: -1, userInfo: nil)))
            }
            
            do {
                let response = try JSONDecoder().decode(RecipesResponses.self, from: data)
                completion(.success(response.results))
            } catch {
                completion(.failure(error))
            }
            
        }.resume()
    }
}

This is where I take in the recipe responses:这是我接受食谱回复的地方:


struct RecipesResponses: Codable {
    let title: String
    let version: Double
    let href: String
    let results: [Recipe]
}

struct Recipe: Codable {
    
    
    let title, href, ingredients, thumbnail: String
    
    var detail:  URL {
        URL(string: href)!
    }
    
    var thumb:  URL {
        URL(string: thumbnail)!
    }
}

This is my recipe ViewModel:这是我的食谱 ViewModel:


class RecipeViewModel: ObservableObject {
    
    @Published var recipes = [Recipe]()
    @Published var isLoading = false
    
    private let service = RecipeService()
    
    init() {
        loadData()
    }
    
    private func loadData() {
        isLoading = true
        service.getRecipes{ [weak self] result in
            DispatchQueue.main.async {
                self?.isLoading = false
                switch result {
                case .failure(let error):
                    print(error.localizedDescription)
                case .success(let recipes):
                    self?.recipes = recipes
                }
            }
        }
    }
    
    
}

This is my view where I list out the API responses:这是我的观点,我列出了 API 响应:


struct ListView: View {
    @ObservedObject var viewModel = RecipeViewModel()
    
    var body: some View {
        NavigationView {
            List(viewModel.recipes, id: \.href) { recipe in
                NavigationLink (destination: RecipeDetailView()) {
                    HStack{
                        CachedImageView(recipe.thumb)
                            .mask(Circle())
                            .frame(width: 80)
                        VStack(alignment: .leading)  {
                            Text(recipe.title)
                                .font(.largeTitle)
                                .foregroundColor(.black)
                                .padding()
                        }
                    }
                    .buttonStyle(PlainButtonStyle())
                }
            }
            .navigationBarTitle(Text("All Recipes"))
        }
    }
}

struct ListView_Previews: PreviewProvider {
    static var previews: some View {
        ListView()
    }
}

This is the view where I would like to list out the recipe details and link to the webpage.这是我想列出食谱详细信息并链接到网页的视图。 This is where I am struggling to be able to pull the API data into:这是我努力将 API 数据提取到:


struct RecipeDetailView: View {
    @ObservedObject var viewModel = RecipeViewModel()
    
    var body: some View {
        Text("Detail View")
    }
}

struct RecipeDetailView_Previews: PreviewProvider {
    static var previews: some View {
        RecipeDetailView()
    }
}

Images of app应用图片

You can change RecipeDetailView to accept a Recipe as a parameter:您可以更改RecipeDetailView以接受Recipe作为参数:

struct RecipeDetailView: View {
    var recipe : Recipe
    
    var body: some View {
        Text(recipe.title)
        Link("Webpage", destination: recipe.detail)
        //etc
    }
}

Then, in your NavigationLink , pass the Recipe to it:然后,在您的NavigationLink中,将Recipe传递给它:

NavigationLink(destination: RecipeDetailView(recipe: recipe)) {

One thing I'd warn you about is force unwrapping the URL s in Recipe using !我要警告您的一URL Recipe使用! -- you should know that if you ever get an invalid/malformed URL, this style of unwrapping will crash the app. -- 你应该知道,如果你得到一个无效/格式错误的 URL,这种展开方式会使应用程序崩溃。


Update, to show you what the preview might look like:更新,向您展示预览的样子:

struct RecipeDetailView_Previews: PreviewProvider {
    static var previews: some View {
        RecipeDetailView(recipe: Recipe(title: "Recipe name", href: "https://google.com", ingredients: "Stuff", thumbnail: "https://linktoimage.com"))
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM