[英]Should a dictionary be converted to a class or struct in Swift?
我正在開發一個本地 iOS 應用程序,該應用程序從我們也控制的 Web 服務接收 JSON 格式的數據。 計划是在大約 18 個月內更換后端數據庫以支持不同的平台。
考慮到這一點,我們希望確保 iOS 應用程序將相對容易適應新的數據源,特別是因為我們可能會更改通過 JSON 從服務器接收的關聯數組中使用的鍵。
有兩個目標:
為每個 PHP 請求創建一個位置,如果需要,可以在其中修改密鑰。 這將避免挖掘代碼以查找諸如job["jobNumber"]
。
清理我們現有的代碼以消除像job["jobNumber"]
這樣的引用。
我們都是 Swift 新手,沒有 Objective-C 經驗,但我認為 Struct 或 Class 適合創建像job.jobNumber
這樣的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
要像這樣訪問它,您需要將字典轉換為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)
}
我通常使用價值類來實現你想要做的事情。 在我的項目中,我做了類似以下的事情:
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尚未得到很好支持的反思。 即使有反射並且你想出了一個聰明的方法來實現你需要的東西,如果數據非常大,它可能會非常慢。
絕對是結構的工作。 結構是線程安全的,不需要由ARC管理。 一些研究發現,與一般課程相比,它們的工作速度要快30,000倍。 結構還提供默認初始值設定項,因此您的代碼將更清晰。 同樣在這種情況下,您不必擔心繼承/子類化。 您很可能也不希望將字典視為引用類型。 如果你能夠,面向協議編程范例建議在類上使用結構。
struct Job {
let jobNumber: Int
let jobName: String
let client: String
}
關於“邏輯”我的兩分錢。 )所有關於使用結構等的正確...)
不要在dict或JSON中保留(盡可能多的來自web do ..)數據,始終將其轉換為struct。
很多有效的,想想例如關於在tableview中排序..
您可以像這樣向 Dictionary 添加擴展以獲取通用對象:
extension Dictionary where Key == String, Value: Any {
func object<T: Decodable>() -> T? {
if let data = try? JSONSerialization.data(withJSONObject: self, options: []) {
return try? JSONDecoder().decode(T.self, from: data)
} else {
return nil
}
}
}
並在任何[String: Any]
字典上像這樣使用:
let object: MyDecodableStruct? = dictionary.object()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.