Swift - Простое исправление ошибки «Элемент экземпляра нельзя использовать для типа»? - PullRequest
0 голосов
/ 13 сентября 2018

Вот JSON-декодирование / анализ, который я сделал на основе страницы isSteamDown JSON :

struct Instruction: Decodable {
    let statuses: [Status]
    let message, messageURL: String
    let status: Bool
    let load, time: Int

    enum CodingKeys: String, CodingKey {
        case statuses, message
        case messageURL = "message_url"
        case status, load, time
    }
}

А вот код, который я написал, чтобы попытаться декодировать его:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        let url = "https://issteamdown.com/status.json"
        let urlObj = URL(string: url)

        URLSession.shared.dataTask(with: urlObj!) {(data, response, error) in

            do {
                guard let json = (try? JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers)) as? [String: Any] else {
                        return
                    }
                for statusCheck in json {
                    print(Instruction.status)
                }
            } catch {
                print(error)
            }
        }.resume()
    }
}

У меня ошибка со строкой печати здесь:

for statusCheck in json {
    print(Instruction.status)
}

и ошибка следующая:

Элемент экземпляра 'status'не может использоваться для типа «Инструкция»

Что меня интересует, так это: каково решение этой конкретной проблемы с моим кодом?

Также: есть ли общее решение для этого, которое обычно работает для этого формата ошибок?

Также, если не так много вопросов, не могли бы вы объяснить причину своего ответа в видеОбыватель терминов, насколько это возможно?


РЕДАКТИРОВАТЬ : я попытался изменить "Instruction.status" на "statusCheck.status", и он вернул ошибку:

Значение типа кортежа '(ключ: строка, значение: любое) "не имеет статуса члена"

Ответы [ 2 ]

0 голосов
/ 13 сентября 2018

Статус также должен адаптироваться к Decodable. И вы должны использовать метод JSONDecodable, как показано ниже.

struct Status: Decodable {
    let title: String
    let code: Int
    let status: Bool
    let time: Int
}

struct Instruction: Decodable {
    let statuses: [Status]
    let message, messageURL: String
    let load: Int

    enum CodingKeys: String, CodingKey {
        case statuses, message
        case messageURL = "message_url"
        case load
    }
}

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        let url = "https://issteamdown.com/status.json"
        let urlObj = URL(string: url)

        URLSession.shared.dataTask(with: urlObj!) {(data, response, error) in
            guard let data = data else { return }
            do {
                let json = try JSONDecoder().decode(Instruction.self, from: data)
                json.statuses.forEach { status in
                    print(status)
                }
            } catch {
                print(error)
            }

            }.resume()
    }
}
0 голосов
/ 13 сентября 2018

Лучше использовать JSONDecoder вместо JSONSerialization для Decodable типов.

let decoder = JSONDecoder()
guard let instruction = try decoder.decode(Instruction.self, from: data!) else { return }
print(instruction.status) // no need for 'for' loop!

Ниже приведен код в контексте существующего кода:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        let url = "https://issteamdown.com/status.json"
        let urlObj = URL(string: url)

        URLSession.shared.dataTask(with: urlObj!) {(data, response, error) in

            do {
                // write the above code here
            } catch {
                print(error)
            }
        }.resume()
    }
}
...