英文:
Struct with protocol as property type does not conform to protocols 'Decodable' and 'Encodable'
问题
Here is the translation of the code you provided:
我有一个名为`UISectionModel`的结构体,只有一个名为`section`的属性,该属性遵循一个名为`UISectionProtocol`的协议,如下所示:
```swift
struct UISectionModel: Codable {
let section: UISectionProtocol
}
这是UISectionProtocol
协议的实现:
protocol UISectionProtocol: Codable {
var identifier: String? { get }
}
正如您所看到的,我需要让UISectionModel
遵循Codable
协议,但我一直收到一个错误,指出它既不遵循Decodable
也不遵循Encodable
,尽管唯一的属性类型已经遵循了Codable
。我怀疑这与这个类型是一个协议有关,但我无法确定导致错误出现的确切原因或如何修复它。
我尝试将section
的类型替换为符合UISectionProtocol
的枚举:
struct UISectionModel: Codable {
let section: UIDefaultSection
}
enum UIDefaultSection: UISectionProtocol {
case imageSection(section: UIImageSection)
case labelSection(section: UILabelSection)
var identifier: String? {
switch self {
case .imageSection(let section): return section.identifier
case .labelSection(let section): return section.identifier
}
}
}
这使错误消失了,但我在思考section
是否需要是符合UISectionProtocol
的任何类型,而不仅仅限于UIDefaultSection
。
<details>
<summary>英文:</summary>
I have a struct `UISectionModel` with only one property `section`, which has a protocol `UISectionProtocol` for a type, as follows:
struct UISectionModel: Codable {
let section: UISectionProtocol
}
Here is the implementation of the `UISectionProtocol` protocol:
protocol UISectionProtocol: Codable {
var identifier: String? { get }
}
As you can see, I need `UISectionModel` to conform to the `Codable` protocol, but I keep getting an error stating that it does not conform to neither `Decodable` or `Encodable`, even though the only property's type is already conforming to `Codable`. I suspect it has to do with the fact that this type is a protocol, but I can't figure the exact reason that is causing the error to appear or how to fix it.
Would appreciate some insight!
I tried replacing the type of `section` with an enum that conforms to `UISectionProtocol`:
struct UISectionModel: Codable {
let section: UIDefaultSection
}
enum UIDefaultSection: UISectionProtocol {
case imageSection(section: UIImageSection)
case labelSection(section: UILabelSection)
var identifier: String? {
switch self {
case .imageSection(let section): return section.identifier
case .labelSection(let section): return section.identifier
}
}
}
This made the error go away, but I'm thinking that `section` needs to be of any type that conforms to `UISectionProtocol`, instead of being limited only to `UIDefaultSection`.
</details>
# 答案1
**得分**: 2
我认为问题在于您可能认为以下代码段:
```swift
protocol UISectionProtocol: Codable
意味着UISectionProtocol符合Codable。但实际上它并不符合。协议不会符合协议。您可能想要一个泛型:
struct SectionModel<T: SectionProtocol>: Codable {
let section: T
}
protocol SectionProtocol: Codable {
var identifier: String? { get }
}
(请注意,我已经去掉了您的类型名称中非法的UI前缀;该前缀仅属于Apple。)
英文:
I think the problem is that you probably believe that saying
protocol UISectionProtocol: Codable
means that UISectionProtocol conforms to Codable. it doesn't. A protocol does not conform to a protocol. You probably want a generic:
struct SectionModel<T: SectionProtocol>: Codable {
let section: T
}
protocol SectionProtocol: Codable {
var identifier: String? { get }
}
(Note that I have stripped the illegal UI prefix off your type names; that prefix belongs to Apple alone.)
答案2
得分: 1
你遇到的问题是由不符合 Codable 协议的协议引起的。当你在 UISectionModel 结构体中包含一个 UISectionProtocol 字段时,编译器无法保证所有符合类型也都是 Codable 的。
要解决这个问题,你可以将 UISectionModel 定义为泛型,并添加一个类型约束以确保 section 属性也是 Codable 的。以下是你代码的更新版本,我认为这可能会解决你的问题。
protocol UISectionProtocol: Codable {
var identifier: String? { get }
}
struct UISectionModel<T: UISectionProtocol>: Codable where T: Codable {
let section: T
}
struct MySection: UISectionProtocol, Codable {
var identifier: String?
}
英文:
The issue you experienced is caused by protocols that don't conform to Codable. When you include a UISectionProtocol field in your UISectionModel struct, the compiler cannot guarantee that all conforming types are also Codable.
To fix this problem you can make UISectionModel generic and add a type constraint to ensure the section property is also codable. Here is an updated version of your code. I think this may solve your issue.
protocol UISectionProtocol: Codable {
var identifier: String? { get }
}
struct UISectionModel<T: UISectionProtocol>: Codable where T: Codable {
let section: T
}
struct MySection: UISectionProtocol, Codable {
var identifier: String?
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论