I have the protocol like this
protocol ViewBuilder {
associatedtype In
associatedtype Out
func build(_ data: In?) -> Out?
}
I have the concrete struct like these. TitleTypeView and ButtonTypeView have the same super class.
struct HeaderTitleBuilder: ViewBuilder {
func build(_ data: DataSource?) -> ViewFactory? {
guard let data = data else { return nil }
return TitleTypeView(data)
}
}
struct HeaderButtonBuilder: ViewBuilder {
func build(_ data: DataSource?) -> ViewFactory? {
guard let data = data else { return nil }
return ButtonTypeView(data)
}
}
I have to combine the Builders struct into HeaderBuilder
struct TestStruct {
func create() {
HeaderBuilder(titleBuilder: HeaderTitleBuilder()
, seeallBuilder: HeaderButtonBuilder())
}
}
struct HeaderBuilder
{
private(set) var titleBuilder: some ViewBuilder = HeaderTitleBuilder()
private(set) var buttonBuilder: some ViewBuilder = HeaderButtonBuilder()
}
I got this error
Cannot convert value of type 'HeaderTitleBuilder' to expected argument type 'some ViewBuilder'
Cannot convert value of type 'HeaderButtonBuilder' to expected argument type 'some ViewBuilder'
So I try to use protocol as a generic constraint
struct HeaderBuilder <T: ViewBuilder>
where T.In == DataSource, T.Out == ViewFactory {
private(set) var titleBuilder: T = HeaderTitleBuilder()
private(set) var buttonBuilder: T = HeaderButtonBuilder()
}
DataSource and ViewFactory are all protocols without associatedtype.
I got this error.
Conflicting arguments to generic parameter 'T' ('HeaderTitleBuilder' vs. 'HeaderButtonBuilder')
I guess the compiler is using HeaderTitleBuilder and HeaderButtonBuilder to infer the type of T. But it is not what I want. I just need to T to be a protocol type that allows me to pass any Builder type.
CodePudding user response:
Since ViewBuilder
is a protocol, when you try make T
a concrete type, it creates a conflict whether that type T
is HeaderTitleBuilder
or HeaderButtonBuilder
. T
cannot be both at the same time.
You can instead make both have a separate generic parameter, e.g,:
struct HeaderBuilder<TitleBuilder: ViewBuilder, ButtonBuilder: ViewBuilder> where TitleBuilder.In == DataSource, TitleBuilder.Out == ViewFactory, ButtonBuilder.In == DataSource, ButtonBuilder.Out == ViewFactory {
private(set) var titleBuilder: TitleBuilder
private(set) var buttonBuilder: ButtonBuilder
}