Сбой при доступе к свойствам объекта после декодирования из JSON - PullRequest
0 голосов
/ 23 июня 2018

Я декодирую значение JSON в объект. Объект выглядит как и ожидалось, но когда я пытаюсь получить доступ к его свойству.

enter image description here

let jsonData = try JSONSerialization.data(withJSONObject: JSON, options: [])
let decoder = JSONDecoder()
let doctor = try! decoder.decode(Doctor.self, from: jsonData)
let txt = "\(doctor.title). \(doctor.firstName) \(doctor.lastName)" // Runtime crash: (Thread 1: EXC_BAD_ACCESS (code=1, address=0x40))

Сбой во время выполнения: (Поток 1: EXC_BAD_ACCESS (код = 1, адрес = 0x40))

Классное лицо:

import UIKit

class Person: Codable {
    let firstName: String
    let lastName: String
    let imageURL: URL

    private enum CodingKeys: String, CodingKey {
        case firstName
        case lastName
        case imageURL = "profileImgPath"
    }

    init(firstName: String, lastName: String, imageURL:URL) {
        self.firstName = firstName
        self.lastName = lastName
        self.imageURL = imageURL
    }
}

Класс доктора:

import UIKit

class Doctor: Person {
    var title: String


    private enum CodingKeys: String, CodingKey {
        case title
    }

    init(firstName: String, lastName: String, imageURL:URL, title: String) {
        self.title = title
        super.init(firstName: firstName, lastName: lastName, imageURL: imageURL)
    }

    required init(from decoder: Decoder) throws {

        let values = try decoder.container(keyedBy: CodingKeys.self)
        self.title = try values.decode(String.self, forKey: .title)
        try super.init(from: decoder)
    }

}

1 Ответ

0 голосов
/ 24 июня 2018

Когда я попробовал ваш код, он выдал ту же ошибку, и в ходе расследования я обнаружил, что это проблема в Swift 4.1. Вы можете проверить ниже,

https://bugs.swift.org/browse/SR-7090

Возможным решением на данный момент может быть небольшая перестановка, как показано ниже,

Удалите Codable соответствие из базового класса, т.е. Person, но вы все равно можете декодировать члены базового класса, сохранив метод init с docoder для вызова из дочерних классов. Дочерние классы теперь будут соответствовать Codable.

class Person {
    let firstName: String
    let lastName: String
    let imageURL: URL

    private enum CodingKeys: String, CodingKey {
        case firstName
        case lastName
        case imageURL = "profileImgPath"
    }

    init(firstName: String, lastName: String, imageURL:URL) {
        self.firstName = firstName
        self.lastName = lastName
        self.imageURL = imageURL
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        self.firstName = try values.decode(String.self, forKey: .firstName)
        self.lastName = try values.decode(String.self, forKey: .lastName)
        self.imageURL = try values.decode(URL.self, forKey: .imageURL)
    }
}

class Doctor: Person, Codable {
    var title: String


    private enum CodingKeys: String, CodingKey {
        case title
    }

    init(firstName: String, lastName: String, imageURL:URL, title: String) {
        self.title = title
        super.init(firstName: firstName, lastName: lastName, imageURL: imageURL)
    }

    required override init(from decoder: Decoder) throws {

        let values = try decoder.container(keyedBy: CodingKeys.self)
        self.title = try values.decode(String.self, forKey: .title)
        try super.init(from: decoder)
    }  
}

Теперь, если у вас есть следующий json, он будет работать как положено.

let json = """
{
  "title":"SomeTitle",
  "firstName": "SomeFirstName",
  "lastName": "SomeLastName",
  "profileImgPath": "urlPath"
}
""".data(using: .utf8)!

let decoder = JSONDecoder()
let doctor = try! decoder.decode(Doctor.self, from: json)
print(doctor.firstName)
print(doctor.lastName)
print(doctor.title)
...