Кодировать / декодировать структуры с использованием Encodable / Decodable от Swift 4 - PullRequest
0 голосов
/ 08 октября 2018

Я не так привык к структурам, и единственный известный мне способ использования структур - это так ...

struct UserDetails {
  let name: String
  let message: String

  init(name: String, message: String) {
    self.name = name
    self.message = message
  }
}

И как только я получу значения name и message,Я добавляю их в структуру примерно так ...

let userDetails = UserDetails(name: theName, message: theMessage)

Затем это добавляется в массив типа структуры примерно так ...

self.userDetailsArray.append(userDetails) 

Теперь, наконец, когда я хочу получить индивидуальное имя или сообщение, я получаю это так ...

let user = userDetailsArray[indexPath.row]
cell.userNameLabel.text = user.name
cell.messageLabel.text = user.message

Это также отлично работает.Но меня беспокоит то, что ... что я указал выше, это очень старый метод, так как swift также разработал протоколы NSCoding, а затем Codable.Но я не знаю, как их реализовать.

Надеюсь, кто-нибудь покажет, как я могу применить NSCoding/Codable протоколы к примеру, который я упомянул выше ...

Ответы [ 2 ]

0 голосов
/ 08 октября 2018

Ваш код в порядке.Чтобы применить Codable для синтаксического анализа / хранения / извлечения списка пользовательских данных, вам необходимо определить свою структуру, например, ниже,

struct UserDetails: Codable {
    let name: String
    let message: String

    enum CodingKeys: String, CodingKey {
        //Uncomment the following commentted lines, if your JSON formatted data comes with different keys like bellow
        case name       //= "user_name"
        case message    //= "user_message"
    }

    init(name: String, message: String) {
        self.name = name
        self.message = message
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(name, forKey: .name)
        try container.encode(message, forKey: .message)
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        name = try container.decode(String.self, forKey: .name)
        message = try container.decode(String.self, forKey: .message)
    }
}

Чтобы проанализировать ответ от вызова веб-API, вы можете использовать следующую функцию

func makeAPICall(){
    guard let url = URL(string: "https://www.your-web-api") else { return }
    URLSession.shared.dataTask(with: url) { (data, response, error) in
        guard let data = data else { return }
        do {
            let decoder = JSONDecoder()
            let userDetails = try decoder.decode([UserDetails].self, from: data)
            print(userDetails)
        } catch let err {
            print("Error", err)
        }
    }.resume()
}

Чтобы сохранить свой список данных пользователя, вы можете написать эту функцию следующим образом:

func storeUserDetails(userDetails: [UserDetails]) {
    do {
        let data = try PropertyListEncoder().encode(userDetails)
        let success = NSKeyedArchiver.archiveRootObject(data, toFile: filePath(key: "file.archive"))
        print(success ? "Successful save" : "Save Failed")
    } catch {
        print("Save Failed")
    }
}

Чтобы получить свой список данных пользователя, используйте эту функцию

func retrieveUserDetails() -> [UserDetails]? {
    guard let data = NSKeyedUnarchiver.unarchiveObject(withFile: filePath(key: "file.archive")) as? Data else { return nil }
    do {
        let products = try PropertyListDecoder().decode([UserDetails].self, from: data)
        return products
    } catch {
        print("Retrieve Failed")
        return nil
    }
}

и вспомогательную функциючтобы получить путь к файлу

func filePath(key:String) -> String {
    let manager = FileManager.default
    let url = manager.urls(for: .documentDirectory, in: .userDomainMask).first
    return (url!.appendingPathComponent(key).path)
}

Некоторые хорошие чтения:

  1. Кодирование и декодирование пользовательских типов
  2. Кодирование, декодирование и сериализация в Swift 4
  3. Все о Codable в Swift 4
0 голосов
/ 08 октября 2018

Много примеров вы можете найти в интернете.Вот общая функция, которая использует протокол Codable.Давайте рассмотрим ваш пример:

struct UserDetails: Codable {
  let name: String, message: String
}

Теперь давайте взглянем на замечательное расширение из gist :

extension Encodable {
    func encode(with encoder: JSONEncoder = JSONEncoder()) throws -> Data {
        return try encoder.encode(self)
    }
}

extension Decodable {
    static func decode(with decoder: JSONDecoder = JSONDecoder(), from data: Data) throws -> Self {
        return try decoder.decode(Self.self, from: data)
    }
}

, которое делает только простую функцию *Значения 1010 * и decode основаны на указанном Class.

Теперь становится проще, как если бы вы просто пропустили data получение от API.

if let arrUserDetails: [UserDetails] = try? [UserDetails].decode(from: data!) {
    print("UserDetails \(arrUserDetails)")   
}

Так вы можете использовать новейшие протоколы Encodable и Decodable.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...