- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我一直在寻找一种在结构中具有通用属性的方法,该属性在运行时定义类型,例如:
struct Dog {
let id: String
let value: ??
}
json
对象时。
node
可以是
int
、
string
、
bool
、数组等,但除了可以更改的类型之外,对象
node
保持不变。
protocols
失败(得到通常的
protocol 'X' can only be used as a generic constraint because it has Self or associated type requirements
错误),我想出了 2 个不同的解决方案,#0 使用
type erasure
和 #1 使用
type-erasure
和
generics
。
struct AnyDog: Encodable {
enum ValueType: Encodable {
case int(Int)
case string(String)
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .int(let value):
try container.encode(value)
case .string(let value):
try container.encode(value)
}
}
}
let id: String
let value: ValueType
init(_ dog: DogString) {
self.id = dog.id
self.value = .string(dog.value)
}
init(_ dog: DogInt) {
self.id = dog.id
self.value = .int(dog.value)
}
}
struct DogString: Encodable{
let id: String
let value: String
var toAny: AnyDog {
return AnyDog(self)
}
}
struct DogInt: Encodable {
let id: String
let value: Int
var toAny: AnyDog {
return AnyDog(self)
}
}
let dogs: [AnyDog] = [
DogString(id: "123", value: "pop").toAny,
DogInt(id: "123", value: 123).toAny,
]
do {
let data = try JSONEncoder().encode(dogs)
print(String(data: data, encoding: .utf8)!)
} catch {
print(error)
}
struct AnyDog: Encodable {
enum ValueType: Encodable {
case int(Int)
case string(String)
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .int(let value):
try container.encode(value)
case .string(let value):
try container.encode(value)
}
}
}
let id: String
let value: ValueType
}
struct Dog<T: Encodable>: Encodable{
let id: String
let value: T
var toAny: AnyDog {
switch T.self {
case is String.Type:
return AnyDog(id: id, value: .string(value as! String))
case is Int.Type:
return AnyDog(id: id, value: .int(value as! Int))
default:
preconditionFailure("Invalid Type")
}
}
}
let dogs: [AnyDog] = [
Dog<String>(id: "123", value: "pop").toAny ,
Dog<Int>(id: "123", value: 123).toAny,
]
do {
let data = try JSONEncoder().encode(dogs)
print(String(data: data, encoding: .utf8)!)
} catch {
print(error)
}
[{"id":"123","value":"pop"},{"id":"123","value":123}]
scalable
,但是对于添加的每种类型,仍然需要在 2 个不同的区域进行更改。
value
像这样是可选的:
struct Dog: Encodable {
// This is the key to the solution: bury the type of value inside a closure
let valueEncoder: (Encoder) throws -> Void
init<T: Encodable>(id: String, value: T?) {
self.valueEncoder = {
var container = $0.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(value, forKey: .value)
}
}
enum CodingKeys: String, CodingKey {
case id, value
}
func encode(to encoder: Encoder) throws {
try valueEncoder(encoder)
}
}
let dogs = [
Dog(id: "123", value: 123),
Dog(id: "456", value: nil),
]
do {
let data = try JSONEncoder().encode(dogs)
print(String(data: data, encoding: .utf8)!)
} catch {
print(error)
}
T
并抛出以下错误:
generic parameter 'T' could not be inferred
Optional
给出了
value
类型,我正在寻找一种使用 Rob 的答案的可能性:
[{"id":"123","value":123},{"id":"456","value":null}]
value
赋予值
nil
,以至于我没有意识到
nil
没有任何类型导致推理错误。
let optString: String? = nil
let dogs = [
Dog(id: "123", value: 123),
Dog(id: "456", value: optString),
]
最佳答案
如果您所描述的确实是您想要的,则无需任何这些类型的橡皮擦即可完成。你所需要的只是一个闭包。 (但这假设 Dog
确实只存在于编码,正如您所描述的那样,除此之外没有任何东西需要 value
。)
struct Dog: Encodable {
// This is the key to the solution: bury the type of value inside a closure
let valueEncoder: (Encoder) throws -> Void
init<T: Encodable>(id: String, value: T) {
self.valueEncoder = {
var container = $0.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(value, forKey: .value)
}
}
enum CodingKeys: String, CodingKey {
case id, value
}
func encode(to encoder: Encoder) throws {
try valueEncoder(encoder)
}
}
value
仅在
valueEncoder
内部使用,世界其他地方不需要知道它的类型(狗甚至不需要知道它的类型)。这就是类型删除的全部内容。它不需要制作额外的包装类型或通用结构。
DogString
这样的类型和
DogInt
,您也可以通过添加协议(protocol)来做到这一点:
protocol Dog: Encodable {
associatedtype Value: Encodable
var id: String { get }
var value: Value { get }
}
struct DogEncoder: Encodable {
let valueEncoder: (Encoder) throws -> Void
init<D: Dog>(_ dog: D) {
self.valueEncoder = {
var container = $0.container(keyedBy: CodingKeys.self)
try container.encode(dog.id, forKey: .id)
try container.encode(dog.value, forKey: .value)
}
}
enum CodingKeys: String, CodingKey {
case id, value
}
func encode(to encoder: Encoder) throws {
try valueEncoder(encoder)
}
}
struct DogString: Dog {
let id: String
let value: String
}
struct DogInt: Dog {
let id: String
let value: Int
}
let dogs = [
DogEncoder(DogString(id: "123", value: "pop")),
DogEncoder(DogInt(id: "123", value: 123)),
]
let data = try JSONEncoder().encode(dogs)
关于swift - 具有通用属性的结构符合 Swift 中的 Encodable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60096473/
我们如何让 SwiftUI 对象,尤其是 Image,符合 Hashable 协议(protocol)? 我知道它们符合 Equatable 协议(protocol),所以主要问题是如何获取哈希值,或
我遇到了一些符合 AVAudioPlayerDelegate 的奇怪问题。以下正是我在一个全新的 Xcode 项目中所拥有的: import UIKit import AVFoundation cla
我一辈子都弄不明白为什么我会收到此类不符合 NSCoding 协议(protocol)的错误。也许另一双眼睛会有所帮助。我试图添加注释以明确每个函数在做什么。 import Foundation im
关闭。这个问题需要details or clarity .它目前不接受答案。 想改进这个问题吗? 通过 editing this post 添加细节并澄清问题. 关闭 9 年前。 Improve t
所有现代浏览器都理解 HTML,所以除了在键盘最右侧编写更多字符之外,兼容 XHTML 的意义何在。 最佳答案 没有一点我能想到的。 W3C 已经取消了 XHTML 2.0,尽管应该有一个 XHTML
我正在设计一个订单系统,状态设计模式似乎很合适,因为订单可以更改其状态,从而更改订单允许的功能。下面是我的基本类图: 我不喜欢这种方法,因为客户端无法查看某个方法是否受支持并且违反了里氏原则。我在下面
我正在考虑使用图形数据库来存储 IFC数据。理想情况下,数据库应该提供一种方法来定义 IFC 架构中定义的所有规则类型。但是,我不认为有任何这样的数据库,因为 IFC 中的某些规则类型非常复杂并且需要
我所在的组织必须满足 FISMA 对启用 FIPS 的系统的要求。我正在尝试做的一件事是为我们的密码实现哈希算法。我对此有很多选择:SHA-2、MD5、bcrypt(使用 Blowfish)、RIPE
我正在尝试实现我的自定义 CoreData Carpark 实体以符合 MKAnnotation,就像我们如何使 class 对象符合 >MKAnnotation. 我根据以下帖子调整了我的实现:th
我在 project-Swift.h 文件中收到名为“CBCentralManagerDelegate”的 No 类型或协议(protocol)。不知道我在这里哪里出错了。我认为这与 swift.h
我正在尝试读取之前写入 NVM 闪存的变量的值。 我的代码是: uintptr_t address = getAddress(); //[MISRA C++ Rule 5-2-8] cast from
所以我有这个练习要解决。我必须创建第一个。一个名为 Printable 的接口(interface),它有一个 put() 方法,该方法将接受实现 Comparable 的对象。 完成 interfa
我的问题涉及 IEEE 754 单精度数字。假设我有一个结构: typedef struct __ieee754 { int sign; int exponent; int mant
我需要使用 map,键为 uint32_t,值为 Meshes。我希望将网格布局在连续的内存中以 boost 性能,因为它们将经常被连续访问。 我想知道有哪些内存分配器库可以提供以下内容; 分配给连续
在处理小对象时,有哪些分配器可用于 STL。我已经尝试过使用 Boost 的池分配器,但没有得到任何性能提升(实际上,在某些情况下性能下降相当大)。 最佳答案 你没有说你使用的是什么编译器,但它可能带
我想做什么 我有一种划分事物的方法。此方法不会对数组进行完全排序;它只是简单地对数组进行分区,以便一侧的所有元素(某些预先确定的“中心”或“中点值”——但它不必导致均匀拆分)小于“中心”和另一侧的所有
假设我需要开发一个 REST 银行应用程序允许创建/销毁银行账户以及对帐户进行以下操作:withdraw/credit/getBalance。 创建帐户 PUT/银行/约翰 这里我使用 PUT 而不是
假设我有一个 struct 符合我的模型的 Equatable,如下所示: struct Model: Equatable { var a: Int = 0 var b: String
我目前正在研究 Decodable、Encodable 和 friend ,试图理解它背后的“魔法”。 以下是我发现不寻常的一件事: class Person: Decodable { var n
在 Swift 书中,枚举的例子很好用 enum CompassPoint: String { case north, south, east, west } var northCom = C
我是一名优秀的程序员,十分优秀!