使用TextField中的值执行API调用,并在SwiftUI中显示结果



希望使用文本字段中的值执行API调用,并在列表中显示结果。在使用文本字段中的$name值到url,然后使API调用时遇到困难

到目前为止我的代码

WebService.swift

import Foundation
public class UserFetcher: ObservableObject {
@Published var shoes: [Shoe] = []
@Published private var name: String = ""

init(){
load()
}

func load() {
// let url = URL(string: "https://api.thesneakerdatabase.com/v1/sneakers?limit=10&name=wolf%20in%20sheeps%20clothing")! // the format the API requires
let url = URL(string: "https://api.thesneakerdatabase.com/v1/sneakers?limit=10&name=" + name)!

URLSession.shared.dataTask(with: url) {(data,response,error) in
do {
if let d = data {
let decodedLists = try JSONDecoder().decode(APIResponse.self, from: d)
DispatchQueue.main.async {
//  self.users = decodedLists
self.shoes = decodedLists.shoeResults
}
}else {
print("No Data")
}
} catch {
print ("Error")
}

}.resume()

}
}

ContentView.swift

import Foundation
import SwiftUI
import Combine
import SDWebImage
import SDWebImageSwiftUI

struct ContentView: View {
@ObservedObject var fetcher = UserFetcher()
@State private var name: String = ""

var body: some View {
NavigationView  {
VStack {
VStack(alignment: .leading) {
TextField("Search", text: $name)
}
List(fetcher.shoes) { Shoe in

VStack (alignment: .leading) {
Text(Shoe.name)
Text(Shoe.shoe)
.font(.system(size: 11))
.foregroundColor(Color.gray)
Text(Shoe.brand)
.font(.system(size: 11))
.foregroundColor(Color.gray)
Text(Shoe.styleId)
.font(.system(size: 11))
.foregroundColor(Color.gray)
Text(".(Shoe.year)")
.font(.system(size: 11))
.foregroundColor(Color.gray)
WebImage(url: URL(string: "(Shoe.media.thumbUrl)"))
.resizable()
.aspectRatio(contentMode: .fill)
}

}

}
.navigationBarTitle(Text("Search"))
}

}

我相信这是很明显的事情,但在过去的两个小时里,我一直在盯着它看,似乎无法工作。任何指示都将不胜感激,谢谢

尝试以下操作:

public class UserFetcher: ObservableObject {
@Published var shoes: [Shoe] = []

init(){
//load() <- remove this
}

func load(_ name: String) { //<-- add parameter
....
}
struct ContentView: View {
@ObservedObject var fetcher = UserFetcher()
@State private var name: String = ""

var body: some View {
NavigationView  {
VStack {
VStack(alignment: .leading) {
TextField("Search", text: $name)
}
List(fetcher.shoes) { Shoe in
...
}
}.onAppear(fetcher.load(name)) //<--- begin to load
}
}

如果你想要在TextField中键入并看到结果更新的正常行为,你可能想要这样的东西(请参阅关于更改内容的内联注释(:

import SwiftUI
import Combine
public class UserFetcher: ObservableObject {

@Published var shoes: [Shoe] = []
@Published var name: String = "" // Not private any more

private var cancellable : AnyCancellable?

init() {
cancellable = $name
.debounce(for: .seconds(1), scheduler: RunLoop.main) //only run once the text has been static for 1 second
.sink { (newSearch) in
self.load(searchTerm: newSearch)
}
}

func load(searchTerm: String) { //take the search term as a parameter
guard !searchTerm.isEmpty, let url = URL(string: "https://api.thesneakerdatabase.com/v1/sneakers?limit=10&name=(searchTerm)") else {
return //don't search if the term is empty or the URL is invalid
}

URLSession.shared.dataTask(with: url) {(data,response,error) in
do {
if let d = data {
let decodedLists = try JSONDecoder().decode(APIResponse.self, from: d)
DispatchQueue.main.async {
self.shoes = decodedLists.shoeResults
}
}else {
print("No Data")
}
} catch {
print ("Error: (error)") //print your error here
}

}.resume()

}
}

struct ContentView: View {
@ObservedObject var fetcher = UserFetcher()

var body: some View {
NavigationView  {
VStack {
VStack(alignment: .leading) {
TextField("Search", text: $fetcher.name) //using the name property from fetcher now
}
List(fetcher.shoes) { shoe in //don't use capital letters for variable names -- not idiomatically correct Swift and it can get confused with your `Shoe` type
VStack (alignment: .leading) {
Text(shoe.name)
Text(shoe.shoe)
.font(.system(size: 11))
.foregroundColor(Color.gray)
Text(shoe.brand)
.font(.system(size: 11))
.foregroundColor(Color.gray)
Text(shoe.styleId)
.font(.system(size: 11))
.foregroundColor(Color.gray)
Text(".(shoe.year)")
.font(.system(size: 11))
.foregroundColor(Color.gray)
}

}

}
.navigationBarTitle(Text("Search"))
}
}
}

我还注意到,在测试时,您使用前一个问题中的Shoe结构从API中得到错误——请确保retailPriceInt?而不是Int,因为有时API不会返回该字段的值。

我还将注意到,您可以通过使用Futureload问题转化为可以链接到Combine调用中的内容,从而使这一点更加巧妙,但这是值得其他研究或不同问题的内容(此处不在范围内(。

相关内容

  • 没有找到相关文章

最新更新