Не удается найти «сообщения» в ошибке области видимости в SwiftUI

#swift #swiftui

#swift #swiftui

Вопрос:

Я получаю сообщение об ошибке cannot find 'posts' in scope . Я пытался найти онлайн-решение, однако не нашел, которое решило бы эту проблему.

contentView.swift

 struct ContentView: View {
    var body: some View {
        NavigationView{
            List(posts) {  //error on this line
                post in
                Text(post.title)
            }
             .navigationBarTitle("Hacker News")
         }
     }
 }


  struct Results: Decodable {
      let hits: [Post]
  }

  struct Post: Decodable, Identifiable {

      var id: String {
          return objectId
      }
        let objectId: String
        let title: String
        let url: String
        let points: Int
  }
  
 class NetworkManager {
    
    
    func fetchData() {
        if let url = URL(string: "https://hn.algolia.com/api/v1/search?tags=front_page"){
            let session = URLSession(configuration: .default)
            let task = session.dataTask(with: url) { (data, response, error) in
                if error == nil{
                    let decoder = JSONDecoder()
                    if let safeData = data{
                        do {
                            let results=try decoder.decode(Results.self, from: safeData)
                            
                        } catch {
                            print(error)
                        }
                    
                    }
                }
            }
            task.resume()
        }
    }
}
  

Комментарии:

1. Является posts ли глобальная переменная? Из вставленного кода я не видел, чтобы он объявлялся и инициализировался.

2. Конечно, вы нигде не объявляли posts свойство в struct. Я предполагаю, что вам нужно начать с docs.swift.org/swift-book/LanguageGuide/TheBasics.html

3. @ZaimRamlan Я обновил оставшийся код, пожалуйста, дайте мне знать, можно ли что-нибудь сделать сейчас?

4. @Asperi, я сделаю это сейчас, можете ли вы сказать мне, как исправить этот код?

Ответ №1:

Не удается найти «сообщения» в области видимости

Это означает, что вы не создали никакой вызываемой переменной posts .

Также обратите внимание, что ваш код NetworkManager также выдает предупреждение:

Инициализация неизменяемого значения «результаты» никогда не использовалась; рассмотрите возможность замены присваиванием «_» или его удаления

Это связано с тем, что данные, полученные с помощью NetworkManager , нигде не используются.

Короче говоря, проблема в том, что это NetworkManager никак не связано / не используется ContentView .


Возможное решение — создать NetworkManager ObservableObject и создать @Published свойство типа [Post] :

 class NetworkManager: ObservableObject { // make ObservableObject
    @Published var posts = [Post]() // create `posts` here
    
    func fetchData() {
        if let url = URL(string: "https://hn.algolia.com/api/v1/search?tags=front_page") {
            let session = URLSession(configuration: .default)
            let task = session.dataTask(with: url) { data, response, error in
                if error == nil {
                    let decoder = JSONDecoder()
                    if let safeData = data {
                        do {
                            let results = try decoder.decode(Results.self, from: safeData)
                            DispatchQueue.main.async {
                                self.posts = results.hits // assign fetched data to `posts`
                            }
                        } catch {
                            print(error)
                        }
                    }
                }
            }
            task.resume()
        }
    }
}
  

Теперь вам нужно использовать NetworkManager в ContentView :

 struct ContentView: View {
    @StateObject private var networkManager = NetworkManager() // or `@ObservedObject` for iOS 13
    
    var body: some View {
        NavigationView {
            List(networkManager.posts) { post in // use `posts` from `networkManager`
                Text(post.title)
            }
            .navigationBarTitle("Hacker News")
        }
        .onAppear {
            networkManager.fetchData() // fetch data when the view appears
        }
    }
}
  

Также у вас есть опечатка в objectId -> она должна быть objectID :

 struct Post: Decodable, Identifiable {
    var id: String {
        return objectID
    }

    let objectID: String
    let title: String
    let url: String
    let points: Int
}
  

Если вы не хотите менять имя, вы можете использовать CodingKeys вместо:

 struct Post: Decodable, Identifiable {
    enum CodingKeys: String, CodingKey {
        case objectId = "objectID", title, url, points
    }
    
    var id: String {
        return objectId
    }

    let objectId: String
    let title: String
    let url: String
    let points: Int
}