Почему мой код JSON в Swift не анализируется?

Отказ от ответственности: очень простой вопрос ниже. Я пытаюсь изучить основы разработки 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'

Более того, я пытаюсь добавить массив «Строки» в одну основную переменную String «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()
    }
}

Как сделать HTTP-запрос в Javascript?
Как сделать HTTP-запрос в Javascript?
В JavaScript вы можете сделать HTTP-запрос, используя объект XMLHttpRequest или более новый API fetch. Вот пример для обоих методов:
0
0
105
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Скорее всего, вы хотели этого (потому что 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)
                    }
                }
            }
        }
    }
}

Спасибо. Невероятно полезное предложение... Последний вопрос: как бы вы предложили добавить к этому кнопку «Обновить»? Я безуспешно пытался использовать кнопку ("Обновить") {FetchPoem} над именем автора.

Simbeul 22.12.2020 07:24

Переместите все из init в FetchPoem в отдельную функцию, например. fetch, который вы сможете вызвать и из init для первоначального извлечения стихотворения, и из кнопки просмотра для извлечения следующего случайного стихотворения.

Asperi 22.12.2020 07:28

Будет ли это выглядеть как отредактированный код выше? Кстати, спасибо за вашу помощь!

Simbeul 22.12.2020 07:36

Я опубликую новый ... Спасибо в любом случае

Simbeul 22.12.2020 07:48

Другие вопросы по теме