我正在开发一个本机iOS应用程序,它从我们也可以控制的Web服务接收JSON格式的数据。计划是在18个月内改变后端数据库,转而采用不同的平台。
考虑到这一点,我们希望确保iOS应用程序相对容易适应新的数据源,特别是因为我们可能会更改通过JSON从服务器接收的关联数组中使用的密钥。 / p>
有两个目标:
为每个PHP请求创建一个位置,如果需要,可以修改密钥。这样可以避免挖掘代码来查找job["jobNumber"]
。
清理现有代码,以消除job["jobNumber"]
等参考资料。
我们都是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
答案 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。
很多效率,例如考虑在表视图中进行排序。