Swift - простое исправление ошибки «не удается использовать член экземпляра для типа»?

Вот "декодирование" / парсинг 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)
}

и ошибка выглядит следующим образом:

Instance member 'status' cannot be used on type 'Instruction'

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

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

Кроме того, если это не слишком много вопросов, не могли бы вы объяснить причину своего ответа как можно более непрофессионально?


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

Value of tuple type '(key: String, value: Any)' has no member 'status'

Что такое Status?

ielyamani 13.09.2018 18:42
1
1
1 086
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Для типов 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()
    }
}

Простите за невежество, но где в коде я должен это поместить? Я предполагаю, что я могу заменить охранника, который у меня есть прямо сейчас, на охрану, которое вы предоставили, но имеет ли значение, где я помещаю строку "let decoder"? Это звучит многообещающе, поскольку я помню, как в руководстве по декодированию, которое я видел, использовалось что-то под названием JSONDecoder, но нужно ли мне что-нибудь импортировать?

bluewizard3 13.09.2018 18:35

@ bluewizard3 Смотрите редактирование. Вам не нужно ничего импортировать. Я думаю, что это в модуле Swift, который импортирован неявно.

Sweeper 13.09.2018 18:39

@ bluewizard3 Также не забудьте сделать так, чтобы Status соответствовал Codable, если вы еще этого не сделали.

Sweeper 13.09.2018 19:35

Вы имеете в виду соответствие Decodable?

bluewizard3 13.09.2018 19:37

@ bluewizard3 Да, но это не имеет значения. Мой ответ сработал для вас?

Sweeper 13.09.2018 19:39

К сожалению, нет, теперь у меня есть ошибка в предпоследней закрывающей скобке документа, в которой говорится об ожидаемом объявлении (у меня такое же количество открытых / закрытых фигурных скобок и круглых скобок), и ошибка в строке URLSession.shared.dataTask, в которой говорится: " Недопустимое преобразование из функции бросания типа '(_, _, _) throws -> ()' в "

bluewizard3 13.09.2018 20:58

можем ли мы переместить это в другое место, чтобы «избежать длительных обсуждений в комментариях»? Может быть, Reddit PM или что-то в этом роде?

bluewizard3 13.09.2018 21:00
Ответ принят как подходящий

Статус должен также адаптироваться 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()
    }
}

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