是否有更好的泛型语法?贝莱德的代码在一开始就给了我巨大的丑陋的泛型定义。
struct ViewUserSettings<TypeGif: ModelGifProtocol, TypeFont: ModelFontProtocol, TypeMagicText: ModelMagicTextProtocol, TypePreSetAnswer: ModelPreSetAnswerProtocol>: View where TypeGif: Hashable, TypeFont: Hashable, TypeMagicText: Hashable, TypePreSetAnswer: Hashable我必须在泛型中定义Hashable,否则编译器在SwiftUI ForEach中使用此协议时会出错。
ModelGif.swift
// MARK: - Protocol
enum GifType: String, Codable {
case fooA = "fooA more"
case fooB = "fooB more"
case fooC = "fooC more"
// MARK: Properties
var fileName600px: String {
switch self {
case .fooA: return "fooAHQ"
case .fooB: return "fooBHQ"
case .fooC: return "fooCHQ"
}
}
var fileName80px: String {
switch self {
case .fooA: return "fooALQ"
case .fooB: return "fooBLQ"
case .fooC: return "fooCLQ"
}
}
}
protocol ModelGifProtocol: Codable {
var gif: GifType { get }
}
// MARK: - Module
struct ModelGif: ModelGifProtocol, Hashable {
// MARK: Properties
let gif: GifType
// MARK: Initialization
init(_ gif: GifType) {
self.gif = gif
}
// MARK: Static Properties
static var fooA = Self(.fooA)
static var fooB = Self(.fooB)
static var fooC = Self(.fooC)
}ModelMagicText.swift
// MARK: - Protocol
protocol ModelMagicTextProtocol: Codable {
var id: UUID { get }
var context: String { get }
init(_ context: String, id: UUID) throws
init(_ context: String) throws
}
// MARK: - Module
struct ModelMagicText: ModelMagicTextProtocol, Hashable {
// MARK: Properties
let id: UUID
let context: String
// MARK: Initialization
init(_ context: String, id: UUID) throws {
guard context.count <= 30 else { throw ContextError.tooLong } // restricted at ViewAnimatingCircleText.modifyDynamicText()
self.context = context.uppercased()
self.id = id
}
init(_ context: String) throws {
try self.init(context, id: UUID())
}
init(_ model: ModelMagicTextProtocol) throws {
try self.init(model.context, id: model.id)
}
// MARK: Static Properties
static let defaultText = try! ModelMagicText("foooooooooooo")
}
// MARK: - Extension: ContextError
extension ModelMagicText {
enum ContextError: Error {
case tooLong
}
}发布于 2021-10-02 17:55:09
我们可以更好地使用多行设置格式。我们还可以将Hashable约束移到泛型参数列表中:
struct ViewUserSettings<
TypeGif: ModelGifProtocol & Hashable,
TypeFont: ModelFontProtocol & Hashable,
TypeMagicText: ModelMagicTextProtocol & Hashable,
TypePreSetAnswer: ModelPreSetAnswerProtocol & Hashable
>: View {
var gif: TypeGif
var font: TypeFont
var magicText: TypeMagicText
var preSetAnswer: TypePreSetAnswer
var body: some View { EmptyView() }
}只有在具有相等约束时才需要where子句,但是示例代码没有任何等式约束。
如果将每个模型协议更改为从Hashable继承,则可以完全消除Hashable约束:
protocol ModelGifProtocol: Hashable { }
protocol ModelFontProtocol: Hashable { }
protocol ModelMagicTextProtocol: Hashable { }
protocol ModelPreSetAnswerProtocol: Hashable { }
struct ViewUserSettings<
TypeGif: ModelGifProtocol,
TypeFont: ModelFontProtocol,
TypeMagicText: ModelMagicTextProtocol,
TypePreSetAnswer: ModelPreSetAnswerProtocol
>: View {
...还有一个问题,你是否需要这样冗长的名字。你真的需要Type和Model前缀吗?
protocol GifProtocol: Hashable { }
protocol FontProtocol: Hashable { }
protocol MagicTextProtocol: Hashable { }
protocol PreSetAnswerProtocol: Hashable { }
struct ViewUserSettings<
Gif: GifProtocol,
Font: FontProtocol,
MagicText: MagicTextProtocol,
PreSetAnswer: PreSetAnswerProtocol
>: View {
var gif: Gif
var font: Font
var magicText: MagicText
var preSetAnswer: PreSetAnswer
var body: some View { EmptyView() }
}请记住,您仍然可以将SwiftUI的Font类型称为SwiftUI.Font in ViewUserSettings。
您没有给出如何定义您的协议的任何细节。你真的需要你自己的ModelFontProtocol吗?SwiftUI的Font已经是Hashable,所以如果您只需要使用具体的Font类型,代码就会更简单。也许您也可以使用具体的类型来代替您的其他协议,但是我们不能不了解它们是如何定义的。
如果您对多个视图使用相同的类型参数和约束集,则有一些方法可以将常见的内容分解出来。如果是这样的话,你应该编辑你的问题,以包括更多的示例代码。
https://stackoverflow.com/questions/69417961
复制相似问题