你不想在每次加载页面时都创建一个新的
Binding
。而是应该使用自定义的
ParseableFormatStyle
。
struct OptionalStringParseableFormatStyle: ParseableFormatStyle {
var parseStrategy: Strategy = .init()
func format(_ value: String?) -> String {
value ?? ""
}
struct Strategy: ParseStrategy {
func parse(_ value: String) throws -> String? {
value
}
}
}
然后使用它
TextField("My Label", value: $myValue, format: OptionalStringParseableFormatStyle())
使其通用化
我更喜欢使用具有静态便利性的通用版本,可以适用于任何类型。
extension Optional {
struct FormatStyle<Format: ParseableFormatStyle>: ParseableFormatStyle
where Format.FormatOutput == String, Format.FormatInput == Wrapped {
let formatter: Format
let parseStrategy: Strategy<Format.Strategy>
init(format: Format) {
self.formatter = format
self.parseStrategy = .init(strategy: format.parseStrategy)
}
func format(_ value: Format.FormatInput?) -> Format.FormatOutput {
guard let value else { return "" }
return formatter.format(value)
}
struct Strategy<OutputStrategy: ParseStrategy>: ParseStrategy where OutputStrategy.ParseInput == String {
let strategy: OutputStrategy
func parse(_ value: String) throws -> OutputStrategy.ParseOutput? {
guard !value.isEmpty else { return nil }
return try strategy.parse(value)
}
}
}
}
extension ParseableFormatStyle where FormatOutput == String {
var optional: Optional<FormatInput>.FormatStyle<Self> { .init(format: self) }
}
由于字符串在大多数情况下都具有格式样式,因此我创建了一个名为ParseableFormatStyle
的标识。
extension String {
struct FormatStyle: ParseableFormatStyle {
var parseStrategy: Strategy = .init()
func format(_ value: String) -> String {
value
}
struct Strategy: ParseStrategy {
func parse(_ value: String) throws -> String {
value
}
}
}
}
extension ParseableFormatStyle where Self == String.FormatStyle {
static var string: Self { .init() }
}
extension ParseableFormatStyle where Self == Optional<String>.FormatStyle<String.FormatStyle> {
static var optional: Self { .init(format: .string) }
}
现在你可以将其用于任何值。例如:
TextField("My Label", value: $myStringValue, format: .optional)
TextField("My Label", value: $myStringValue, format: .string.optional)
TextField("My Label", value: $myNumberValue, format: .number.optional)
TextField("My Label", value: $myDateValue, format: .dateTime.optional)
@State var test = ""
?如果不行,那么当你的字符串为nil
时,你想要TextField
做什么? - user7014451String?
,你可以认为nil
和""
是“等价的”,但如果你的数据模型包含CLLocation?
-什么是nil
的“等价物”?SwiftUI通常不与Optional
很好地配合。 - Grimxn