Обертки свойств с общими (необязательными) значениями по умолчанию для пользователя - PullRequest
1 голос
/ 10 октября 2019

При наличии соответствующей ссылки:

https://github.com/apple/swift-evolution/blob/master/proposals/0258-property-wrappers.md#user-defaults

Мы начали использовать оболочки свойств для UserDefaults, оно легко работает снеобязательные свойства.

Однако установка nil необязательного свойства завершается с помощью:

[User Defaults] Попытка установить объект списка не-свойств как NSUserDefaults / CFPreferencesзначение для ключа «someKeyThatWeSet»

Завершение работы приложения из-за необработанного исключения «NSInvalidArgumentException», причина: «Попытка вставить нулевой объект списка свойств для ключа« someKeyThatWeSet »'

TheКод ниже можно проверить непосредственно на игровой площадке:

@propertyWrapper
struct C2AppProperty<T> {
    let key: String
    let defaultValue: T

    init(_ key: String, defaultValue: T) {
        self.key = key
        self.defaultValue = defaultValue
    }

    var wrappedValue: T {
        get {
            return UserDefaults.standard.object(forKey: key) as? T ?? defaultValue
        }
        set {
            UserDefaults.standard.set(newValue, forKey: key)
        }
    }
}

struct C2User {
    @C2AppProperty("userID", defaultValue: nil)
    public static var publicUserID: String?
}

print(C2User.publicUserID)
C2User.publicUserID = "edusta"
print(C2User.publicUserID)
C2User.publicUserID = nil
print(C2User.publicUserID)

Ожидаемый:

ноль

Необязательно <"edusta">

ноль

Найдено:

ноль

Необязательно <"edusta">

libc ++ abi.dylib: завершается с неисследованным исключением типа NSException

Что я пробовал до сих пор:

set {
    // Comparing non-optional value of type 'T' to nil always returns false.
    if newValue == nil {
        UserDefaults.standard.removeObject(forKey: combinedKey)
    } else {
        UserDefaults.standard.set(newValue, forKey: combinedKey)
    }
}

WЧто за проверка нужна, чтобы узнать, что newValue равно nil? Или Optional<nil>?

1 Ответ

4 голосов
/ 10 октября 2019

Этот код работает для меня:

@propertyWrapper
struct UserDefault<T> {
    private let key: String
    private let defaultValue: T
    private let userDefaults: UserDefaults

    init(_ key: String, defaultValue: T, userDefaults: UserDefaults = .standard) {
        self.key = key
        self.defaultValue = defaultValue
        self.userDefaults = userDefaults
    }

    var wrappedValue: T {
        get {
            return userDefaults.object(forKey: key) as? T ?? defaultValue
        }
        set {
            if let value = newValue as? OptionalProtocol, value.isNil() {
                userDefaults.removeObject(forKey: key)
            } else {
                userDefaults.set(newValue, forKey: key)
            }
        }
    }
}

fileprivate protocol OptionalProtocol {
    func isNil() -> Bool
}

extension Optional : OptionalProtocol {
    func isNil() -> Bool {
        return self == nil
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...