#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.html3. @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
}