提问人:Sergei Kirasirov 提问时间:6/21/2023 更新时间:6/21/2023 访问量:28
如何在视图中正确使用 extern 结构?
How to use extern Structure in a View correctly?
问:
我找不到在 ContentView 中使用我的结构的方法。 结构正确填充,但仅此而已。 如何替换视图中的示例数组:
let countries = ["Germany", "Egypt", "Italy"] // example
来自以下国家/地区的真实阵列:
let countries: CountriesWikiData = await decodeWikiData(from: countriesQuery)
struct CountriesWikiData: Decodable {
let head: CountriesHead
let results: CountriesResults
}
struct CountriesHead: Decodable {
let vars: [String]
}
struct CountriesResults: Decodable {
let bindings: [CountriesBindings]
}
struct CountriesBindings: Decodable {
let country: [String: String]
let countryLabel: [String: String]
}
func decodeWikiData<T: Decodable>(from url: String) async -> T {
let url = URL(string: url)!
let request = URLRequest(url: url)
do {
let (data, _) = try await URLSession.shared.data(for: request)
guard
let jsonObj = try? JSONSerialization.jsonObject(with: data, options: []),
let jsonData = try? JSONSerialization.data(withJSONObject: jsonObj, options: .prettyPrinted)
else {
fatalError("Cannot convert data to JSON.")
}
guard let strc = try? JSONDecoder().decode(T.self, from: jsonData)
else {
fatalError("Cannot make a structure.")
}
return strc // Wheeeee!!
} catch {
fatalError("Cannot get data from URL.")
}
}
struct ContentView: View {
/*
SELECT DISTINCT ?country ?countryLabel
WHERE
{
?country wdt:P31 wd:Q3624078.
SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
}
*/
let countriesQuery = "https://query.wikidata.org/sparql?query=SELECT%20DISTINCT%20%3Fcountry%20%3FcountryLabel%0AWHERE%0A%7B%0A%20%20%3Fcountry%20wdt%3AP31%20wd%3AQ3624078.%0A%20%20SERVICE%20wikibase%3Alabel%20%7B%20bd%3AserviceParam%20wikibase%3Alanguage%20%22en%22%20%7D%0A%7D&format=json"
let countries = ["Germany", "Egypt", "Italy"] // example
@State var selectedCountry = ""
//let countries: CountriesWikiData = await decodeWikiData(from: countriesQuery)
var body: some View {
VStack {
Picker("", selection: $selectedCountry) {
ForEach(countries, id: \.self) {
Text($0)
}
}
}
}
}
答:
1赞
workingdog support Ukraine
6/21/2023
#1
您可以尝试此方法,以使用模型结构显示 API 调用的结果,如示例代码中所示。
该方法使用修改后的 with 和 结构。
视图中的更新修饰符
和 a 与重要的CountriesBindings
Country
CountryLabel
func decodeWikiData(...)
.task {...}
Picker
.tag(country.value)
struct CountriesWikiData: Decodable {
let head: CountriesHead
let results: CountriesResults
}
struct CountriesHead: Decodable {
let vars: [String]
}
struct CountriesResults: Decodable {
let bindings: [CountriesBindings]
}
struct CountriesBindings: Codable {
let country: Country
let countryLabel: CountryLabel
}
struct Country: Identifiable, Codable, Hashable {
let id = UUID()
let type: String
let value: String
}
struct CountryLabel: Identifiable, Codable, Hashable {
let id = UUID()
let xmlLang: String
let type: String
let value: String
enum CodingKeys: String, CodingKey {
case xmlLang = "xml:lang"
case type, value
}
}
struct ContentView: View {
let countriesQuery = "https://query.wikidata.org/sparql?query=SELECT%20DISTINCT%20%3Fcountry%20%3FcountryLabel%0AWHERE%0A%7B%0A%20%20%3Fcountry%20wdt%3AP31%20wd%3AQ3624078.%0A%20%20SERVICE%20wikibase%3Alabel%20%7B%20bd%3AserviceParam%20wikibase%3Alanguage%20%22en%22%20%7D%0A%7D&format=json"
@State var countries: [CountryLabel] = []
@State var selectedCountry: String = ""
var body: some View {
VStack {
Text("selected country: \(selectedCountry)")
Picker("", selection: $selectedCountry) {
ForEach(countries) { country in
Text(country.value).tag(country.value)
}
}
}
.task {
let response: CountriesWikiData? = await decodeWikiData(from: countriesQuery)
if let resp = response {
for bin in resp.results.bindings {
countries.append(bin.countryLabel)
}
}
if let first = countries.first {
selectedCountry = first.value
}
}
}
func decodeWikiData<T: Decodable>(from url: String) async -> T? {
if let url = URL(string: url) {
do {
let (data, _) = try await URLSession.shared.data(from: url)
return try JSONDecoder().decode(T.self, from: data)
} catch {
print(error)
}
}
return nil
}
}
评论
0赞
Sergei Kirasirov
6/21/2023
哇。。。多谢!太棒了。
评论