Сохранить кортеж в NSUserDefaults
Я использую кортеж для хранения чего-то подобного.
var accessLavels: (hasInventoryAccess: Bool, hasPayrolAccess: Bool)
accessLavels = (hasInventoryAccess: true, hasPayrolAccess: false)
Теперь я хочу сохранить его в NSUserDefaults
,
NSUserDefaults.standardUserDefaults().setValue(accessLavels, forKey: "AccessLevelKey")
NSUserDefaults.standardUserDefaults().synchronize()
Но я получаю следующую ошибку.
Тип '(hasInventoryAccess: Bool, hasPayrolAccess: Bool)' не соответствует протоколу 'AnyObject'
Как я могу решить эту проблему? Если это невозможно, тогда любые другие предложения по сохранению кортежа приветствуются.
Спасибо.
5 ответов
Я столкнулся с похожим сценарием, пытаясь закодировать кортеж с NSCoder
, Я решаю это путем ручного преобразования кортежа в Dictionary
, Это не очень хорошее решение, так как ключи должны быть изменены в нескольких местах, если кортеж когда-либо изменится.
В моем кортеже было вложенное перечисление, и я дал ему базовый тип (String), из которого я преобразовал необработанное значение. Это была небольшая дополнительная работа, но, к счастью, ваши только примитивы.
# SerializeableTuple.swift
typealias AccessTuple = (hasInventoryAccess: Bool, hasPayrolAccess: Bool)
typealias AccessDictionary = [String: Bool]
let InventoryKey = "hasInventoryAccess"
let PayrollKey = "hasPayrollAccess"
func serializeTuple(tuple: AccessTuple) -> AccessDictionary {
return [
InventoryKey : tuple.hasInventoryAccess,
PayrollKey : tuple.hasPayrolAccess
]
}
func deserializeDictionary(dictionary: AccessDictionary) -> AccessTuple {
return AccessTuple(
dictionary[InventoryKey] as Bool!,
dictionary[PayrollKey] as Bool!
)
}
# Encoding / Decoding
var accessLavels: AccessTuple = (hasInventoryAccess: true, hasPayrolAccess: false)
// Writing to defaults
let accessLevelDictionary = serializeTuple(accessLavels)
NSUserDefaults.standardUserDefaults().setObject(accessLevelDictionary, forKey: "AccessLevelKey")
// Reading from defaults
let accessDic = NSUserDefaults.standardUserDefaults().dictionaryForKey("AccessLevelKey") as AccessDictionary
let accessLev = deserializeDictionary(accessDic)
Вы можете хранить Bool, Float, Int, Object, Double или URL, но не Tuple. Таким образом, у вас есть два варианта, сохраните только два значения hasPayrolAccess и hasPayrolAccess Bool:
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "hasInventoryAccess")
NSUserDefaults.standardUserDefaults().setBool(false, forKey: "hasPayrolAccess")
let hasInventoryAccess = NSUserDefaults.standardUserDefaults().boolForKey("hasInventoryAccess")
println(hasInventoryAccess)
let hasPayrolAccess = NSUserDefaults.standardUserDefaults().boolForKey("hasPayrolAccess")
println(hasPayrolAccess)
Или сохраните его, используя Array of Bool:
var accessLavels = [true,false]
println(accessLavels)
NSUserDefaults.standardUserDefaults().setValue(accessLavels, forKey: "accessLavels")
if let loadAccessLavels = NSUserDefaults.standardUserDefaults().arrayForKey("accessLavels") as? [Bool] {
if let hasInventoryAccess = loadAccessLavels.first {
println(hasInventoryAccess)
}
if let hasPayrolAccess = loadAccessLavels.last {
println(hasPayrolAccess)
}
}
У меня был кортеж с 3 значениями.
Следующий код был использован для сохранения кортежа. По сути, я создал строку из кортежа (с компонентами, разделенными запятой).
let defaultsLoad = NSUserDefaults.standardUserDefaults()
if appSingleton.runwayDestShared != nil
{
// Creating a String from the tuple
let runwayDestString = appSingleton.runwayDestShared!.0 + "," + appSingleton.runwayDestShared!.1 + "," + appSingleton.runwayDestShared!.2
defaultsLoad.setObject(runwayDestString, forKey: "RunwayDest")
}
Чтобы извлечь кортеж, я извлек строку, разбил ее на массив и использовал массив для воссоздания кортежа.
let runwayDestString = defaultsLoad.stringForKey("RunwayDest")
if let runwayDestString = runwayDestString
{
let runwayDestArray = runwayDestString.componentsSeparatedByString(",")
appSingleton.runwayDestShared = (runwayDestArray[0],runwayDestArray[1],runwayDestArray[2])
}
Мне годовалый вопрос, но все же:
let accesLvl : [String:AnyObject] = ["hasInventoryAcces":true, "hasPayrolAccess":false]
NSUserDefaults.standardUserDefaults().setObject(accesLvl, forKey: "accesLevel")
Если вы сохраняете только bools, let accesLvl : [String:Bool]
это лучший вариант.
Если я что-то не получаю (я довольно новичок в Swift и программировании в целом), какая польза от использования "кортежа" над словарем или даже структуры
В документации я не вижу никакого метода -setValue
, На основе документов NSUserDefaults может сохранять только NSString, NSNumber, NSData, NSDictionary, NSArray, NSData и NSDate. Вот ссылка: Ссылка класса NSUserDefaults.
Таким образом, вы не можете сохранить кортеж здесь. А также -setValue
из NSKeyValueCoding
протокол.