在 NSUserDefaults 中保存元组

问题描述 投票:0回答:6

我正在使用元组来存储这样的东西。

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”

如何解决这个问题?如果不可能,那么欢迎任何其他保存元组的建议。

谢谢你。

ios swift ios8 tuples nsuserdefaults
6个回答
8
投票

我遇到了类似的场景,尝试使用

NSCoder
编码元组。我解决这个问题的方法是手动将元组转换为
Dictionary
。这不是一个很好的解决方案,因为如果元组发生变化,则需要在多个位置更改键。

我的元组中有一个嵌套枚举,并给它一个基本类型(字符串),我从中转换了原始值。这是一些额外的工作,但幸运的是你的只是原始的。

# 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)

1
投票

您可以存储 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)

或者使用 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)
    }
}

1
投票

我有一个包含 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])
}

0
投票

我的问题已经有一年了,但仍然:

 let accesLvl : [String:AnyObject] = ["hasInventoryAcces":true, "hasPayrolAccess":false]
 NSUserDefaults.standardUserDefaults().setObject(accesLvl, forKey: "accesLevel")

如果您只保存布尔值,

let accesLvl : [String:Bool]
是更好的选择。

如果我没有得到什么(我对 Swift 和编程都相当陌生),使用“元组”而不是字典,甚至结构会有什么好处


0
投票

在首选项中处理元组的最“类似元组”的方式:

将元组保存到首选项是很常见的事情。

  • 元组的本质在于它们是简单、草率、无类型、未命名、快速且轻量级的数组版本。他们是一个“劣质阵列”。

  • 因此,保存元组的最佳习惯和最自然的方式就是使用劣质数组。

如果元组类型都相同且简单,一定要使用劣质数组。

如果元组类型混合但很容易“另存为”类型,那么一定要使用劣质数组。

这是一个保存“排序列和排序方向”元组的完全常见的示例,每个应用程序都经常使用它。

///For a given screen name save the recent sort col and sense.
func set(forScreen: String, sortColumnSense: (Int, Bool)) {
    UserDefaults.standard.set(
        [sortColumnSense.0, (sortColumnSense.1 ? 1 : 0)],
        forKey: "sortTup_\(forScreen.suffix(64))")
}

///For a given screen name recover the recent sort col sense
func getSortColumnSense(forScreen: String) -> (Int, Bool)? {
    let quasi = UserDefaults.standard.array(forKey: "sortTup_\(forScreen.suffix(64))")
    guard let quasi,
          quasi.count == 2,
          let tup = quasi as? [Int]
    else { return nil }
    return (tup[0], (tup[1] == 0 ? false : true))
}

如果您使用 N 个不同的首选项键,这完全避免了一致性和清理的复杂问题,并且存储/检查的简单临时性质将所有检查逻辑集中到 SSOT,因此任何团队成员都不可能位于不同的页面上,并且完全类型迁移安全,否则如果您使用其他三种方法之一,这将是大量代码。


-1
投票

在文档中,我没有看到任何方法

-setValue
。 根据文档,NSUserDefaults只能保存NSString,NSNumber,NSData,NSDictionary,NSArray,NSData和NSDate。链接在这里: NSUserDefaults 类参考。

所以,你无法在这里保存元组。

-setValue
来自
NSKeyValueCoding
协议。

© www.soinside.com 2019 - 2024. All rights reserved.