json - 为什么我在 Swift 中的 JSON 代码无法解析?
问题描述
免责声明:以下非常基本的问题。我正在努力学习IOS开发的基础知识。
我目前正在尝试将数据从 API 解析到 SwiftUI 项目,但无法成功。
代码如下:
import SwiftUI
struct Poem: Codable {
let title, author: String
let lines: [String]
let linecount: String
}
class FetchPoem: ObservableObject {
// 1.
@Published var poems = [Poem]()
init() {
let url = URL(string: "https://poetrydb.org/random/1")!
// 2.
URLSession.shared.dataTask(with: url) {(data, response, error) in
do {
if let poemData = data {
// 3.
let decodedData = try JSONDecoder().decode([Poem].self, from: poemData)
DispatchQueue.main.async {
self.poems = decodedData
}
} else {
print("No data")
}
} catch {
print("Error")
}
}.resume()
}
}
struct ContentView: View {
@ObservedObject var fetch = FetchPoem()
let joined = fetch.poem.lines.joined(separator: "\n")
var body: some View {
Text(fetch.poem.title)
.padding()
Text( \(joined) )
.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
当前构建失败。它向我抛出了以下错误:
Initializer 'init(_:)' requires that 'Binding<Subject>' conform to 'StringProtocol'
Referencing subscript 'subscript(dynamicMember:)' requires wrapper 'ObservedObject<FetchPoem>.Wrapper'
Value of type 'FetchPoem' has no dynamic member 'poem' using key path from root type 'FetchPoem'
此外,我试图将数组“Lines”附加到一个主字符串变量“Joined”中。但是,我不确定这是否有效......错误是“字符串插值只能出现在字符串文字中”。如果有人知道,希望得到一些帮助...
有任何想法吗?感谢所有帮助。
** 编辑代码 - Q2
import SwiftUI
struct Poem: Codable, Hashable {
let title, author: String
let lines: [String]
let linecount: String
}
class FetchPoem: ObservableObject {
@Published var poems = [Poem]()
func getPoem() {
let url = URL(string: "https://poetrydb.org/random/1")!
// 2.
URLSession.shared.dataTask(with: url) {(data, response, error) in
do {
if let poemData = data {
// 3.
let decodedData = try JSONDecoder().decode([Poem].self, from: poemData)
DispatchQueue.main.async {
self.poems = decodedData
}
} else {
print("No data")
}
} catch {
print("Error")
}
}.resume()
}
}
struct ContentView: View {
@ObservedObject var fetch = FetchPoem()
var body: some View {
VStack {
if let poem = fetch.poems.first {
Button("Refresh") {getPoem}
Text("\(poem.author): \(poem.title)").bold()
Divider()
ScrollView {
VStack {
ForEach(poem.lines, id: \.self) {
Text($0)
}
}
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
解决方案
很可能你想要这个(因为poems
是一个数组) - 用 Xcode 12.1 / iOS 14.1 测试
struct Poem: Codable, Hashable {
let title, author: String
let lines: [String]
let linecount: String
}
// ...
struct ContentView: View {
@ObservedObject var fetch = FetchPoem()
var body: some View {
List {
ForEach(fetch.poems, id: \.self) {
Text("\($0.author): \($0.title)")
}
}
}
}
... ,接下来可能会将其包装成NavigationView/NavigationLink
在目的地视图中显示每首诗。
显示行如下:
var body: some View {
VStack {
if let poem = fetch.poems.first {
Text("\(poem.author): \(poem.title)").bold()
Divider()
ScrollView {
VStack {
ForEach(poem.lines, id: \.self) {
Text($0)
}
}
}
}
}
}
推荐阅读
- php - 降级 PHP 版本 Laravel 5.8
- python - 如何有效地传输数据框中的值?
- spring - 在 Spring MVC 控制器中触发 Camel 路由
- docker - 卷是否可以从处于退出状态的容器中获得?
- jquery - 为什么引导程序中的图标在崩溃时只更改一次?为什么 jquery 代码只运行一次?
- networking - 什么是网络中的抖动变化?
- android-fragments - Room Database 提供的“刷新”LiveData 的最佳方式
- flutter - 如何在 Flutter 中禁用 Web 支持?
- ruby-on-rails - Rails:如何检索数据库凭据以安装 ForestAdmin
- node.js - Node App 仅使用 nodemon 在服务器上运行