swift - 如何存储泛型类型以避免在 Swift 中需要它的内部结构?
问题描述
这个问题最好用一些代码来解释。
第1步
public struct Example<Content: View> {
let content: () -> Content
init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
}
func contentView() -> Content {
self.content()
}
}
第2步
现在当我添加一个内部结构时,编译器会抱怨不支持静态存储属性。
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)
}
}
}
第 3 步
为了消除错误,我们需要将其转换为计算变量。
public static var cancelButtonClicked: ActionKey { get { ActionKey("cancelButtonClicked") } }
问题
除了这已经很烦人之外,它变得更糟。我们还需要为一个完全不依赖它的结构提供一个通用参数。
_ = Example.ActionKey(rawValue: "cancelButtonClicked") // Generic parameter 'Content' could not be inferred
// Fix
_ = Example<AnyView>.ActionKey(rawValue: "cancelButtonClicked")
如果我们能以某种方式避免将泛型类型放在外部作用域中,我们就可以避免它。但是,将类型存储在变量中不会让我使用它。所以我被困住了。有人有答案吗?
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)
}
}
}
将内部结构置于其之外的唯一解决方案是什么?
解决方案
这是可能的方法(但是我会把它放在外面,就像ButtonStyle
在外面一样Button
)......无论如何,它是:
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)
}
}
}
推荐阅读
- c++ - 如何通过可变参数模板表达概念?
- performance - 下一个优化图像:错误模块解析失败,意外字符 ''"
- swiftui - 如何编辑子类对象列表
- ubuntu - 如何修复 libQt5WebKit 符号查找错误?
- elasticsearch - 在 Painless/ELK 中拆分字符串
- javascript - useImperativeHandle 中的递归函数
- javascript - React 为 API 调用的结果设置状态
- python - Python plotly sankey 导出损坏
- crafter-cms - 使用弹性搜索在 Crafer CMS 中进行不区分大小写的搜索?
- javascript - 为什么 redux 存储状态在 render() 中显示为 `false`,即使默认状态是 `true`?