【问题标题】:Swift array of dictionaries with multiple types without using NSDictionary in iOS在 iOS 中不使用 NSDictionary 的具有多种类型的 Swift 字典数组
【发布时间】:2015-10-16 06:01:52
【问题描述】:

我一直在使用 NSDictionary 在 Swift(版本 7 beta 4)中处理一系列字典。该数组是包含不同数据类型的 fmdb 结果的集合。我想最终得到一系列本机 swift 字典,以便使用 swift 集合类型的过滤器功能。以下是我正在使用创建数组的查询函数的 sn-p:

class func query(sql:String) -> [NSDictionary] {
    let dirPaths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,.UserDomainMask, true)
    let docsDir = dirPaths[0] as String
    let databasePath:String = docsDir.stringByAppendingPathComponent("myDB.db")
    let db = FMDatabase(path: databasePath as String)
    var resultsArray:[NSDictionary] = []

    if db.open() {

        let results:FMResultSet? = db.executeQuery(sql, withArgumentsInArray: nil)
        while (results?.next() == true) {
            resultsArray.append(results!.resultDictionary()) //appending query result

        }
        db.close()

    } else {
        print("Error: \(db.lastErrorMessage())")
    }
    return resultsArray
}

我尝试使用 AnyObject,例如:

    class func query(sql:String) -> [[String:AnyObject]] {
    let dirPaths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,.UserDomainMask, true)
    let docsDir = dirPaths[0] as String
    let databasePath:String = docsDir.stringByAppendingPathComponent("Kerbal.db")
    let db = FMDatabase(path: databasePath as String)
    var resultsArray:[[String:AnyObject]] = []

    if db.open() {

        let results:FMResultSet? = db.executeQuery(sql, withArgumentsInArray: nil)
        while (results?.next() == true) {
            resultsArray.append(results!.resultDictionary() as! Dictionary<String,AnyObject>)

        }
        db.close()

    } else {
        print("Error: \(db.lastErrorMessage())")
    }
    return resultsArray
}

但是我不能将resultsArray.filter({$0["fieldName"] == "part"}) 之类的过滤器与AnyObject 一起使用。

我的问题:即使字典有不同的类型,是否可以使用本机 Swift 字典创建这个数组?可以在集合类型上使用新的协议扩展来解决这个问题吗?

欢迎提出任何建议。

【问题讨论】:

  • 你知道字典中有哪些类型吗?文档(在 obj-c 中)没有说明这一点。
  • 我知道每个字典中的三个值将是字符串,而其他值是双精度。

标签: ios swift dictionary swift2


【解决方案1】:

你可能应该采用 Equatable 协议,并不是所有的 AnyObjects 实际上都是这样,因此可能不会进行比较和过滤。

【讨论】:

    【解决方案2】:

    如果你不知道你正在处理哪些对象,你必须像这样使用过滤器:

    resultsArray.filter{ ($0["fieldName"] as? String) == "part"}
    

    因此,您可以选择将值转换为所需的类型并进行比较。

    注意:我使用的是尾随闭包语法。

    作为建议,我会使用包含字典的不同数组的元组:

    // some dummy values
    let resultsArray: [[String : AnyObject]] = [["Hi" : 3], ["Oh" : "String"]]
    
    var result = (doubles: [[String : Double]](), strings: [[String : String]]())
    
    // going through all dictionaries of type [String : AnyObject]
    for dict in resultsArray {
    
        // using switch and pattern matching to cast them (extensible for more types)
        // you have to up cast the dictioanary in order to use patten matching
        switch dict as AnyObject {
        case let d as [String : Double]: result.doubles.append(d)
        case let s as [String : String]: result.strings.append(s)
        default: fatalError("unexpected type")
        }
    }
    
    return result
    

    【讨论】:

    • 这正是我想做的,我可能不清楚我拥有的类型......并不是说我可能有一本包含所有字符串的字典,在一种情况下,在另一种情况下有一本全双打的字典。相反,我有类似于 dictArray = [[name:bob, age:25], [name:bill, age:30]] 的字典。默认情况下,不可能使用本机 swift 字典创建这个字典数组,因为所有类型都必须相同。至少这是我的理解。
    • 在这种情况下,如果您只有几种不同的类型,我会使用元组。所以返回类型是(doubles: [[String : Double]], strings: [[String : String]])。如果你愿意,我还会在我的答案中添加一个示例如何做到这一点。
    • 所以在我的字典是 fmdb 结果的情况下,您将遍历字典的值并确定类型,然后将键值保存到元组的双精度或字符串元素?
    • 感谢您的示例。我没有时间尝试,但我认为这应该可以正常工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-05
    • 2019-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多