Значение в UserDefaults появляется только после перезапуска

Я сохраняю объект Codable и простую строку в UserDefaults и после этого представляю новый экран, где используется это значение. По какой-то причине объект Codable равен нулю, пока я не перезапущу приложение. Строковое значение доступно сразу. Чтобы отладить эту проблему, я попытался получить этот объект, нажав кнопку, но он всегда равен нулю и не имеет значения, когда я пытаюсь получить это значение. появляется только после перезагрузки

var user: Contact? = {
    if let contactData = UserDefaults.standard.data(forKey: Constants.UserDefaultsKey.currentUser),
        let contact = try? JSONDecoder().decode(Contact.self, from: contactData) {
        return contact
    }
    return nil
}()

func storeUser(_ user: Contact) {
    do {
        let encodedUser = try JSONEncoder().encode(user)
        UserDefaults.standard.set(encodedUser, forKey: Constants.UserDefaultsKey.currentUser)
        UserDefaults.standard.set(true, forKey: Constants.UserDefaultsKey.isLoggedIn)
        UserDefaults.standard.synchronize()
    } catch {
        print(error.localizedDescription)
    }
}

struct Contact {
    var id: String?
    var email: String?
}

extension Contact: Codable {

enum ContactEncodingKeys: String, CodingKey {
    case id
    case email = "email_address_work"
}

func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: ContactEncodingKeys.self)
    try container.encode(id, forKey: .id)
    try container.encode(email, forKey: .email)
}

init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: ContactEncodingKeys.self)
    id = try container.decode(String.self, forKey: .id)
    email = try container.decode(String?.self, forKey: .email)
}
}

Таким образом, объект user равен нулю до перезапуска.


person Nikolai Prokofev    schedule 24.07.2018    source источник
comment
Где именно в коде, который вы разместили, у вас возникла проблема? Неясно.   -  person rmaddy    schedule 24.07.2018
comment
Я вижу, что ContactEncodingKeys id не имеет строкового значения. Ключ должен быть строкой. Это может быть проблемой. Вы это заметили?   -  person Shamim Hossain    schedule 24.07.2018
comment
Ваш var user будет инициализирован, как только будет создан экземпляр этого объекта. Если это произойдет до того, как будет установлено значение по умолчанию для пользователя, то user будет равно nil. Это не вычисляемая переменная, поэтому она не переоценивается каждый раз, когда на нее ссылаются. Возможно, вы имели в виду, что это вычисляемая переменная? Также нет необходимости звонить synchronize   -  person Paulw11    schedule 24.07.2018
comment
@ Paulw11 ты прав. Спасибо   -  person Nikolai Prokofev    schedule 24.07.2018
comment
@ShamimHossain Все в порядке, если идентификатор имеет то же строковое значение, что и имя ключа.   -  person Nikolai Prokofev    schedule 24.07.2018
comment
К сведению: вызов synchronize устарел и не нужен.   -  person rmaddy    schedule 24.07.2018


Ответы (1)


В настоящее время, если вы обращаетесь к свойству user перед установкой объекта в UserDefaults, он просто назначит nil и не будет выполнять вычисления снова, пока вы не создадите новый объект этого класса. Измените свойство user на вычисленное, как показано ниже.

var user: Contact? {
    if let contactData = UserDefaults.standard.data(forKey: Constants.UserDefaultsKey.currentUser),
        let contact = try? JSONDecoder().decode(Contact.self, from: contactData) {
        return contact
    }
    return nil
}
person Kamran    schedule 24.07.2018
comment
Спасибо. Были вычислены другие объекты, кроме этого. Тратить так много времени на эту глупую ошибку - person Nikolai Prokofev; 24.07.2018
comment
@NikolaiProkofev, не могли бы вы принять ответ, если он помог вам решить проблему. Спасибо! - person Kamran; 25.07.2018