SwiftUI - if let 条件关闭的替代方法
SwiftUI - alternative to if let with a conditional closure
我正在尝试在 SwiftUI 中实现以下内容:
struct PersonView: View {
@State private var age: Int? = 0
var body: some View {
VStack {
Text("Just a test")
if let self.age > 0 {
Text("Display Age: \(age)")
} else {
Text("Age must be greater than 0!")
}
}
}
}
但是,在 SwiftUI 中,if let
会导致以下错误:
Closure containing control flow statement cannot be used with function builder 'ViewBuilder'
所以在研究了这个主题之后,我遇到了使用 .map
来解包 age
可选的建议。因此,我修改了 VStack
中的代码如下:
Text("Just a test")
self.age.map {elem in
if elem > 0 {
Text("Display Age: \(elem)")
} else {
Text("Age must be greater than 0!")
}
}
但是,在 .map
闭包中包含条件会导致调用 VStack
的行出现以下错误:
' (ViewBuilder.Type) -> (C0, C1) -> TupleView<(C0, C1)>' requires that '()' conform to 'View'
Type '()' does not conform to protocol 'View'
关于如何克服第二组错误的任何建议?或者,是否有另一种方法可以在 SwiftUI 中展开可选值并对其进行评估?真的很喜欢 SwiftUI,但不敢相信解包可选值是一件令人头疼的事情!
Swift 5.3 (Xcode 12)
现在您可以直接在视图构建器中使用条件绑定:
if let age = age {
if age > 0 {
Text("Display Age: \(age)")
} else {
Text("Age must be greater than 0!")
}
} else {
Text("Age not found")
}
重构(也适用于较早的 Swifts)
您可以将代码重构为更基本的代码,例如使用函数:
var body: some View {
VStack {
Text("Just a test")
Text(text(age: age)) // Using the function
}
}
func text(age: Int?) -> String { // Defining the function
guard let age = age else { return "Age not found" }
if age > 0 { return "Display Age: \(age)" }
else { return "Age must be greater than 0!" }
}
一般来说,在需要清理代码的地方使用函数。我希望 Swift 的未来版本将像我们期望的那样直接支持它。
对于这种情况,我更喜欢以下方法
struct PersonView: View {
@State private var age: Int? = 0
var body: some View {
VStack {
Text("Just a test")
AgeText
}
}
private var AgeText: some View {
if let age = self.age, age > 0 {
return Text("Display Age: \(age)")
} else {
return Text("Age must be greater than 0!")
}
}
}
您正在尝试对年龄的值进行两次检查:首先确保它不是 nil
,然后检查它是否大于 0。
您可以使用 map 摆脱潜在的 nil
然后使用三元运算符有条件地更改显示的文本:
var body: some View {
VStack {
Text("Just a test")
age.map { Text( [=10=] > 0 ? "Display Age: \([=10=])" : "Age must be greater than 0!") }
}
}
我正在尝试在 SwiftUI 中实现以下内容:
struct PersonView: View {
@State private var age: Int? = 0
var body: some View {
VStack {
Text("Just a test")
if let self.age > 0 {
Text("Display Age: \(age)")
} else {
Text("Age must be greater than 0!")
}
}
}
}
但是,在 SwiftUI 中,if let
会导致以下错误:
Closure containing control flow statement cannot be used with function builder 'ViewBuilder'
所以在研究了这个主题之后,我遇到了使用 .map
来解包 age
可选的建议。因此,我修改了 VStack
中的代码如下:
Text("Just a test")
self.age.map {elem in
if elem > 0 {
Text("Display Age: \(elem)")
} else {
Text("Age must be greater than 0!")
}
}
但是,在 .map
闭包中包含条件会导致调用 VStack
的行出现以下错误:
' (ViewBuilder.Type) -> (C0, C1) -> TupleView<(C0, C1)>' requires that '()' conform to 'View'
Type '()' does not conform to protocol 'View'
关于如何克服第二组错误的任何建议?或者,是否有另一种方法可以在 SwiftUI 中展开可选值并对其进行评估?真的很喜欢 SwiftUI,但不敢相信解包可选值是一件令人头疼的事情!
Swift 5.3 (Xcode 12)
现在您可以直接在视图构建器中使用条件绑定:
if let age = age {
if age > 0 {
Text("Display Age: \(age)")
} else {
Text("Age must be greater than 0!")
}
} else {
Text("Age not found")
}
重构(也适用于较早的 Swifts)
您可以将代码重构为更基本的代码,例如使用函数:
var body: some View {
VStack {
Text("Just a test")
Text(text(age: age)) // Using the function
}
}
func text(age: Int?) -> String { // Defining the function
guard let age = age else { return "Age not found" }
if age > 0 { return "Display Age: \(age)" }
else { return "Age must be greater than 0!" }
}
一般来说,在需要清理代码的地方使用函数。我希望 Swift 的未来版本将像我们期望的那样直接支持它。
对于这种情况,我更喜欢以下方法
struct PersonView: View {
@State private var age: Int? = 0
var body: some View {
VStack {
Text("Just a test")
AgeText
}
}
private var AgeText: some View {
if let age = self.age, age > 0 {
return Text("Display Age: \(age)")
} else {
return Text("Age must be greater than 0!")
}
}
}
您正在尝试对年龄的值进行两次检查:首先确保它不是 nil
,然后检查它是否大于 0。
您可以使用 map 摆脱潜在的 nil
然后使用三元运算符有条件地更改显示的文本:
var body: some View {
VStack {
Text("Just a test")
age.map { Text( [=10=] > 0 ? "Display Age: \([=10=])" : "Age must be greater than 0!") }
}
}