Reputation: 18204
The problem is best explained with some code.
public struct Example<Content: View> {
let content: () -> Content
init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
}
func contentView() -> Content {
self.content()
}
}
Now when I add an internal struct, the compiler will complain that static stored properties are not supported.
public struct Example<Content: View> {
let content: () -> Content
init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
}
func contentView() -> Content {
self.content()
}
public struct ActionKey: Hashable, Equatable, RawRepresentable {
public static let cancelButtonClicked = ActionKey("cancelButtonClicked") // Static stored properties not supported in generic types
public static func == (lhs: ActionKey, rhs: ActionKey) -> Bool {
return lhs.rawValue == rhs.rawValue
}
public let rawValue: String
public init(rawValue: String) {
self.rawValue = rawValue
}
public init(_ rawValue: String) {
self.init(rawValue: rawValue)
}
}
}
To get rid of the error we need to transform it into a computed variable.
public static var cancelButtonClicked: ActionKey { get { ActionKey("cancelButtonClicked") } }
Besides this already being annoying it gets worse. We also need to supply a generic parameter for a struct that does not depend on it at all.
_ = Example.ActionKey(rawValue: "cancelButtonClicked") // Generic parameter 'Content' could not be inferred
// Fix
_ = Example<AnyView>.ActionKey(rawValue: "cancelButtonClicked")
If we could somehow avoid putting the generic type in the outer scope we can avoid it. However storing the type in a variable won't let me use it. So I am stuck. Does anyone have an answer?
public struct Example<Content: View> {
let content: Any
let contentType: Any.Type
init<Content>(@ViewBuilder content: @escaping () -> Content) {
self.content = content
self.contentType = Content.self
}
func contentView() -> ?? {
self.content() // ??
}
public struct ActionKey: Hashable, Equatable, RawRepresentable {
public static var cancelButtonClicked: ActionKey { get { ActionKey("cancelButtonClicked") } }
public static func == (lhs: ActionKey, rhs: ActionKey) -> Bool {
return lhs.rawValue == rhs.rawValue
}
public let rawValue: String
public init(rawValue: String) {
self.rawValue = rawValue
}
public init(_ rawValue: String) {
self.init(rawValue: rawValue)
}
}
}
Is the only solution to the problem putting the internal struct outside it all?
Upvotes: 2
Views: 607
Reputation: 257779
Here is possible approach (however I'd keep it outside, like ButtonStyle
is outside of Button
)... anyway, here it is:
public struct Example {
private let content: AnyView
init<Content: View>(@ViewBuilder content: @escaping () -> Content) {
self.content = AnyView(content())
}
func contentView() -> some View {
self.content
}
public struct ActionKey: Hashable, Equatable, RawRepresentable {
public static let cancelButtonClicked = ActionKey("cancelButtonClicked") // Static stored properties not supported in generic types
public static func == (lhs: ActionKey, rhs: ActionKey) -> Bool {
return lhs.rawValue == rhs.rawValue
}
public let rawValue: String
public init(rawValue: String) {
self.rawValue = rawValue
}
public init(_ rawValue: String) {
self.init(rawValue: rawValue)
}
}
}
Upvotes: 1