[英]Swift dictionary with mix types (optional and non-optional)
I have a struct that has a method to return a dictionary representation. 我有一个结构,该结构具有返回字典表示形式的方法。 The member variables were a combination of different types (String and Double?)
成员变量是不同类型(字符串和双精度?)的组合
With the following code example, there would be a warning from Xcode (Expression implicitly coerced from 'Double?' to Any) 在下面的代码示例中,将出现来自Xcode的警告(表达式从'Double?'隐式强制为Any)
struct Record {
let name: String
let frequency: Double?
init(name: String, frequency: Double?) {
self.name = name
self.frequency = frequency
}
func toDictionary() -> [String: Any] {
return [
"name": name,
"frequency": frequency
]
}
}
However if it was returning a type [String: Any?], the warning goes away: 但是,如果返回类型[String:Any?],则警告消失:
struct Record {
let name: String
let frequency: Double?
init(name: String, frequency: Double?) {
self.name = name
self.frequency = frequency
}
func toDictionary() -> [String: Any?] {
return [
"name": name,
"frequency": frequency
]
}
}
My question is: Is this correct? 我的问题是:这正确吗? And if it is, can you point me to some Swift documentation that explains this?
如果是的话,您能指出一些解释这个问题的Swift文档吗?
If it isn't, what should it be? 如果不是,那应该是什么?
== EDIT == ==编辑==
The following works too: 以下工作也可以:
struct Record {
let name: String
let frequency: Double?
init(name: String, frequency: Double?) {
self.name = name
self.frequency = frequency
}
func toDictionary() -> [String: Any] {
return [
"name": name,
"frequency": frequency as Any
]
}
}
You can cast frequency
to Any
since the latter can hold any type. 您可以将
frequency
为Any
因为后者可以容纳任何类型。 It is like casting instances of specific Swift type to the Objective-C id type. 就像将特定Swift类型的实例转换为Objective-C id类型一样。 Eventually, you'll have to downcast objects of the type
Any
to a specific class to be able to call methods and access properties. 最终,您将必须将
Any
类型的对象向下转换到特定的类,以便能够调用方法和访问属性。
I would not recommend structuring data in your code using Any
, or if you want to be specific Any?
我不建议您使用
Any
构造代码中的数据,或者如果您要特定于Any?
(when the object may or may not hold some value). (当对象可能具有或不具有某些值时)。 That would be a sign of bad data-modeling.
那将是不良的数据建模的迹象。
From the documentation : 从文档中 :
Any can represent an instance of any type at all, including function types.[...] Use Any and AnyObject only when you explicitly need the behavior and capabilities they provide.
Any可以代表任何类型的实例,包括函数类型。[...] 仅当您明确需要它们提供的行为和功能时, 才使用Any和AnyObject 。 It is always better to be specific about the types you expect to work within your code.
最好对要在代码中使用的类型进行具体说明 。
(emphasis is mine) (重点是我的)
Instead, use the Data
type. 而是使用
Data
类型。 And you would be able to decode Record
or encode it from and into Data
: 这样,您就可以对
Record
进行解码或将其编码为Data
:
struct Record : Codable {
let name: String
let frequency: Double?
init(name: String, frequency: Double?) {
self.name = name
self.frequency = frequency
}
init(data: Data) throws {
self = try JSONDecoder().decode(Record.self, from: data)
}
func toData() -> Data {
guard let data = try? JSONEncoder().encode(self) else {
fatalError("Could not encode Record into Data")
}
return data
}
}
And use it like so: 并像这样使用它:
let record = Record(name: "Hello", frequency: 13.0)
let data = record.toData()
let decodedRecord = try Record(data: data)
print(decodedRecord.name)
print(decodedRecord.frequency ?? "No frequency")
I'd recommend adding Codable
conformance, and letting JSONEncoder
do all the heavy lifting. 我建议添加
Codable
一致性,并让JSONEncoder
完成所有繁重的工作。 If however you are constrained to the toDictionary
approach, then I would advise against [String:Any?]
, since that might result in undefined behaviour (try to print the dictionary for more details). 但是,如果您受限于
toDictionary
方法,则建议不要使用[String:Any?]
,因为这可能会导致未定义的行为(尝试打印字典以获取更多详细信息)。
A possible solution for toDictionary
is to use an array of tuples that gets converted to a dictionary: toDictionary
的可能解决方案是使用元组数组,将其转换为字典:
func toDictionary() -> [String: Any] {
let propsMap: [(String, Any?)] = [
("name", name),
("frequency", frequency)
]
return propsMap.reduce(into: [String:Any]()) { $0[$1.0] = $1.1 }
}
This way the nil properties simply don't receive entries in the output dictionary. 这样,nil属性根本不会在输出字典中接收条目。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.