Ios 如何在SwiftUI中将数据从ContentView传递到子视图
如果这不合理,请原谅,我完全是Swift的初学者。我正在创建一个配方应用程序,它从API中提取数据并在导航链接中列出。当用户单击配方时,我希望它移动到子视图,并显示API中的信息,如配方名称、图像、成分,并有一个带有网页链接的按钮 我能够通过导航链接将数据拉到列表中。但是,现在我不知道如何使用上面列出的所有信息设置recipe details子视图 这就是我调用API的地方:Ios 如何在SwiftUI中将数据从ContentView传递到子视图,ios,swift,swiftui,Ios,Swift,Swiftui,如果这不合理,请原谅,我完全是Swift的初学者。我正在创建一个配方应用程序,它从API中提取数据并在导航链接中列出。当用户单击配方时,我希望它移动到子视图,并显示API中的信息,如配方名称、图像、成分,并有一个带有网页链接的按钮 我能够通过导航链接将数据拉到列表中。但是,现在我不知道如何使用上面列出的所有信息设置recipe details子视图 这就是我调用API的地方: class RecipeService { func getRecipes(_ completion: @es
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()
}
}
这是我的配方视图模型:
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
}
}
}
}
}
这是我列出API响应的视图:
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)!
}
}
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()
}
}
这是我想列出配方详细信息并链接到网页的视图。这就是我努力将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()
}
}
您可以更改
RecipedTailView
以接受配方
作为参数:
struct RecipeDetailView: View {
var recipe : Recipe
var body: some View {
Text(recipe.title)
Link("Webpage", destination: recipe.detail)
//etc
}
}
然后,在导航链接
中,将配方
传递给它:
NavigationLink(destination: RecipeDetailView(recipe: recipe)) {
我要警告你的一件事是使用强制展开配方中的URL
s代码>--您应该知道,如果您收到无效/格式不正确的URL,这种类型的展开将使应用程序崩溃
更新,以显示预览的外观:
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"))
}
}
我的RecipeDetailView“调用中参数'recipe'缺少参数”中出现错误“每次使用RecipeDetailView
时,都必须向其传递recipe
——请参见我在导航链接中如何做到这一点?无论你在哪里使用它,这都必须发生。因此,在预览中,您还必须传递一个配方(您只需创建一个带有伪值的伪配方即可使用)。有关在预览中提供配方的示例,请参阅更新的答案