这是我在论坛上的第一条消息,我希望将其正确张贴。
我正在尝试在SwiftUI中创建一个动态列表,一旦用户在文本字段中键入内容,该列表就会立即更新。
列表使用viaggiatreno.it的API,这是意大利火车公司的服务。
我将使用的特定链接返回以提供给特定URL的字符串开头的火车站列表。
我已经创建了一个车站类,如下所示:
struct Station: Decodable, Identifiable {
var iid = UUID()
var name : String
var id: String
}
还有一个StationFetcher类,该类获取用字符串初始化的API URL,该字符串是用户将从文本字段传递的字符串:
import Foundation
public class StationFetcher : Decodable, ObservableObject {
var stations = [Station]()
var search = ""
init(search: String) {
getJsonData(string: search)
}
func getJsonData(string: String) {
let url = URL(string: "http://www.viaggiatreno.it/viaggiatrenonew/resteasy/viaggiatreno/cercaStazione/" + string)
//string is the initial string of the station
let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
if error != nil {
print(error!)
} else {
if let urlContent = data {
do {
let jsonResult = try JSONSerialization.jsonObject(with: urlContent , options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject
for i in 0..<jsonResult.count {
if let station = jsonResult[i] as AnyObject? {
if let nameStation = station["nomeLungo"] as! String? {
if let idStation = station["id"] as! String? {
let searchItem = Station(name: nameStation, id: idStation)
DispatchQueue.main.async {
self.stations.append(searchItem)
}
}
} else {
print("error catching dictionary value")
}
}
}
} catch {
print("JSON Processing failed")
}
}
}
}
task.resume()
}
}
如何在主SwiftUI视图中进行管理?
import SwiftUI
struct Departure: View {
@State public var selectedStation = ""
@State private var departureDate = Date()
@ObservedObject var fetcher = StationFetcher(search: "")
var body: some View {
NavigationView {
Form {
Section(header: Text("Cerca Stazione di partenza:")) {
TextField("Da dove parti?...", text: $selectedStation)
}
Section(header: Text("Orario:")) {
DatePicker(selection: $departureDate) {
Text("Partenza")
}
}
Section(header: Text("Lista stazioni")){
List(fetcher.stations) { station in
Text(station.name)
}
}
}
.navigationBarTitle("Partenza")
}
}
}
谢谢大家
答案 0 :(得分:1)
感谢您的帮助。我已经部分成功地完成了我要寻找的东西,一部分是为了一件事情。
通过在StationFetcher中使用ObservableObject协议,将@Publish发布到我要更新的变量中,即可更新列表。
test.js
StationFetcher的代码现在为:
struct Departure: View {
@State public var selectedStation = ""
@State private var departureDate = Date()
@ObservedObject var fetcher = StationFetcher(search: "")
var body: some View {
NavigationView {
Form {
Section(header: Text("Cerca Stazione di partenza:")) {
TextField("Da dove parti?...",
text: $selectedStation, onEditingChanged: { _ in
self.fetcher.getJsonData(string: self.selectedStation)
})
}
Section(header: Text("Orario:")) {
DatePicker(selection: $departureDate) {
Text("Partenza")
}
}
Section(header: Text("Lista stazioni")){
List(fetcher.stations) { station in
Text(station.name)
.autocapitalization(.words)
}
}
}
.navigationBarTitle("Partenza")
}
}
}
我唯一无法使用的是对一个字符进行数字化后立即实时更新列表。 现在,只要我在文本字段之外单击或按回车键,该列表就会更新。
我不确定onEditingChanged是否正确。
有人有主意吗?
非常感谢
答案 1 :(得分:0)
安东尼奥。您是说要根据用户的搜索输入来过滤电台列表吗?我建议进行一些小的更改以使这种情况发生。
通常,在ObservableObject中,您可以将@Published添加到实例变量,以使视图在更改时自动更新(例如@Published var stations = [Station]()
)。但是,由于StationFetcher类也符合Decodable,因此您必须自己实现此发布,这可以通过在对象的发布者上调用send()
来完成:
var stations = [Station]() {
didSet {
self.objectWillChange.send()
}
}
因此,在您的出发视图中,您只需要在用户更改搜索字段时触发新搜索。可以使用TextField的可选onEditingChanged
参数来完成此操作,以在用户键入新文本时执行关闭操作:
TextField("Da dove parti?...",
text: $selectedStation,
onEditingChanged: { _ in
self.fetcher.getJsonData(string: self.selectedStation)
})
让我知道这是否适合您!