字典是否应该转换为Swift中的类或结构?

时间:2015-04-10 02:35:59

标签: class swift dictionary struct

我正在开发一个本机iOS应用程序,它从我们也可以控制的Web服务接收JSON格式的数据。计划是在18个月内改变后端数据库,转而采用不同的平台。

考虑到这一点,我们希望确保iOS应用程序相对容易适应新的数据源,特别是因为我们可能会更改通过JSON从服务器接收的关联数组中使用的密钥。 / p>

有两个目标:

  1. 为每个PHP请求创建一个位置,如果需要,可以修改密钥。这样可以避免挖掘代码来查找job["jobNumber"]

  2. 等内容
  3. 清理现有代码,以消除job["jobNumber"]等参考资料。

  4. 我们都是Swift的新手,没有Objective-C经验,但我认为Struct或Class适合创建像job.jobNumber这样的引用。

    字典应该转换为类还是结构?代表如下所示采用Dictionary<String, String>并将其转换为推荐类型的可重用方法的示例代码将非常有用。

    示例词典:

    job = {
        "jobNumber" : "1234",
        "jobName" : "Awards Ceremony",
        "client" : "ACME Productions"
    }
    

    期望的结果:

    println("job name is \(job.name)")
    // prints: job name is Awards Ceremony
    

4 个答案:

答案 0 :(得分:6)

要像这样访问它,您需要将字典转换为Struct,如下所示:

编辑/更新: Swift 3.x

struct Job: CustomStringConvertible {
    let number: Int
    let name, client: String
    init(dictionary: [String: Any]) {
        self.number = dictionary["jobNumber"] as? Int ?? 0
        self.name = dictionary["jobName"] as? String ?? ""
        self.client = dictionary["client"] as? String ?? ""
    }
    var description: String {
        return "Job#: " + String(number) + " - name: " + name + " - client: " + client
    }
}

let dict: [String: Any] = ["jobNumber": 1234,
                                     "jobName"  : "Awards Ceremony",
                                     "client"   : "ACME Productions"]

let job = Job(dictionary: dict)
print(job.number)       //  1234
print(job.name)         //  "Awards Ceremony"
print(job.client)       //  "ACME Productions"
print(job)              // "Job#: 1234 - name: Awards Ceremony - client: ACME Productions"""

编辑/更新:

Swift 4或更高版本您可以使用JSON Codable协议:

struct Job {
    let number: Int
    let name, client: String
}
extension Job: Codable {
    init(dictionary: [String: Any]) throws {
        self = try JSONDecoder().decode(Job.self, from: JSONSerialization.data(withJSONObject: dictionary))
    }
    private enum CodingKeys: String, CodingKey {
        case number = "jobNumber", name = "jobName", client
    }
}
extension Job: CustomStringConvertible {
    var description: String {
        return "Job#: " + String(number) + " - name: " + name + " - client: " + client
    }
}

let dict: [String: Any] = ["jobNumber": 1234,
                           "jobName"  : "Awards Ceremony",
                           "client"   : "ACME Productions"]
do {
    let job = try Job(dictionary: dict)
    print(job.number)       //  1234
    print(job.name)         //  "Awards Ceremony"
    print(job.client)       //  "ACME Productions"
    print(job)              //  "Job#: 1234 - name: Awards Ceremony - client: ACME Productions\n"
} catch {
    print(error)
}

答案 1 :(得分:1)

我通常会使用值类来实现您想要的功能。在我的项目中,我做了类似的事情:

protocol Request : class {
    func toDictionary() -> [String : String]
}

protocol Response : class {
    init(dictionary: [String : String])
}

class MyRequest : Request {
    var var1: Int
    var var2: String

    //Other stuff in class...

    func toDictionary() -> [String : String] {
        //Convert the value to dictionary and return
    }
}

class MyResponse : Response {
    var var1: String
    var var2: Int

    //You could have nested object as members 
    var innerObject: MyInnerResponseClass

    //Other stuff in class...

    var someCalculatedProperty: String {
        return //Calculate property value
    }

    required init(dictionary: [String : String]) {
        //Initialize class from dictionary
    }
}

class MyInnerResponseClass: Response {
    //Class definition here...
}

对于可以用作请求和响应的对象,您可以实现这两种协议。

您需要编写一次翻译代码,但随后可以轻松地在任何地方使用。此外,通过使用计算属性,您可以更轻松。

我不确定你是否可以在Swift中开箱即用。我将需要Swift尚未得到很好支持的反思。即使有反射并且你想出了一个聪明的方法来实现你所需要的东西,如果数据非常大,它可能会很慢。

答案 2 :(得分:0)

绝对是结构的工作。结构是线程安全的,不需要由ARC管理。一些研究发现,与一般课程相比,它们的工作速度要快30,000倍。结构还提供默认初始值设定项,因此您的代码将更清晰。同样在这种情况下,您不必担心继承/子类化。您很可能也不希望将字典视为引用类型。面向协议的编程范例建议如果你能够在类上使用结构。

struct Job {
    let jobNumber: Int
    let jobName: String
    let client: String
}

答案 3 :(得分:0)

关于“逻辑”的两美分。 )关于使用结构等的所有信息都正确...)

请勿将数据(与Web上的数据一样多)保存在dict或JSON中,请始终将其转换为struct。

很多效率,例如考虑在表视图中进行排序。