I want my code to be as reusable as it can be. Writer
and JsonProperties
are Protocols that define plenty of the functionality the related objects require. JsonProperties
conforms to Codable
protocol, but I want to implement a custom method for Core Data implementation, through a Writer
, the question is:
Can I initialize an object that implements a Writer
protocol through the typealias of JsonProperties
?
Right now I'm getting this error:
Cannot convert value of type '[Model]' to expected argument type '[Model.WriterType.Model]'
Here's the code:
protocol Writer {
associatedtype Model: JsonProperties
...
init(in dataStack: DataStack)
}
struct GenericWriter<Model: JsonProperties>: Writer { ... }
protocol JsonProperties: Codable {
associatedtype WriterType: Writer
...
}
struct ConversationProperties: JsonProperties {
typealias WriterType = GenericWriter<Self>
...
}
The implementation I was looking for, but got the error was:
func networkFetch<Model: JsonProperties>(type: Model.Type) -> AnyPublisher<Bool, Error> {
let writer = Model.WriterType(in: dataStack)
...
var objects = [Model]()
...
writer.insert(objects) <- Error here!
My guess this is not the correct implementation of the init()
of a typealias
struct.
The problem you're seeing stems from the fact that you not haven't constrained the associate type WriterType
within JsonProperties
.
Currently, it accepts any WriterType
type conforming to Writer
, regardless of what its Model
is.
What you probably want is for the WriterType
type to have its Model
be the same as the type being conformed to JsonProperties
protocol - so you need to constrain it:
protocol JsonProperties: Codable {
associatedtype WriterType: Writer where WriterType.Model == Self
}
The insert
method accepts a [Model]
, where Model
is the associated type of Writer
.
writer
is of type Model.WriterType
where WriterType
is a Writer
, so writer.insert
accepts Model.WriterType.Model
. Here, the first Model
is the generic parameter of networkFetch
, whereas the second Model
is the associated type of the Writer
protocol.
However, you have created a [Model]
. This Model
refers to the generic parameter of networkFetch
, not the associated type.
There is actually no guarantee that your generic parameter Model
is the same type as Model.WriterTypeModel.Model
. For example, I could do:
struct FooProperties: JsonProperties {
typealias WriterType = GenericWriter<ConversationProperties>
}
And if I pass FooProperties.self
to networkFetch
, the generic parameter Model
would be FooProperties
, but Model.WriterType.Model
would be ConversationProperties
.
There are many ways to fix this.
WriterType
associated type to forbid me from creating a FooProperties
in the first place:protocol JsonProperties: Codable {
associatedtype WriterType: Writer where WriterType.Model == Self
}
Model
:func networkFetch<Model: JsonProperties>(type: Model.Type) -> AnyPublisher<Bool, Error>
where Model.WriterType.Model == Model {
Model.WriterType.Model
instead (this will not work if you are deserialising objects of type Model
and putting them into this array)var objects = [Model.WriterType.Model]()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.