视图通常不允许可选参数值,从而导致如下错误Initializer 'init(_:)' requires that 'String?' conform to 'StringProtocol':
struct Person {
var name : String
}
struct OptionalsExampleView: View {
var person : Person? = Person(name: "Bob")
var body: some View {
VStack() {
Text("Name:")
Text(person?.name)
}
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,从 Xcode 11.4/iOS 13 开始,if letView Builder 块中不允许使用该语句,从而导致出现如下错误Closure containing control flow statement cannot be used with function builder 'ViewBuilder':
struct OptionalsExampleView: View {
var person : Person? = Person(name: "Bob")
var body: some View {
VStack() {
if let person = person { // <-- not allowed
Text("Name:")
Text(person?.name)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
(我知道这个问题已经被回答和问过很多次了。我自己写了这个问题并回答了它,以便有一篇比现有文章更简洁的简短概述文章,以便我可以在出现这个问题的地方链接到它向上)。
a) 在非常简单的情况下,使用可选的后备或带有强制展开的 if 检查(if在 View Builder 块中允许):
struct OptionalsExampleView: View {
var person : Person? = Person(name: "Bob")
var body: some View {
VStack() {
Text(person?.name ?? "")
if person != nil {
Text("Name:")
Text(person!.name)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
b)Optional#map如果存在单个可选值,则用于显示单个视图:
struct OptionalsMapExampleView: View {
var person : Person? = Person(name: "Bob")
var body: some View {
VStack() {
person.map { person in
VStack {
Text("Name:")
Text(person.name)
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
c)if let使用显式返回类型将块包装在组视图中。if let如果它是视图生成器块中的唯一语句,则此处允许。如果块可以返回不同的视图类型,则视图需要包装为AnyView:
struct OptionalsGroupExampleView: View {
var person: Person? = Person(name: "Bob")
var body: some View {
VStack {
Group { () -> AnyView in
if let person = person {
return AnyView(VStack {
Text("Name:")
Text(person.name)
})
} else {
return AnyView(EmptyView())
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
d) 将逻辑提取到一个单独的函数中 -if let此处允许,因为它位于视图构建器块之外。如果函数可以返回不同的视图类型,则需要将视图包装为AnyView:
struct OptionalsFuncExampleView: View {
var person : Person? = Person(name: "Bob")
var body: some View {
VStack() {
personView()
}
}
func personView() -> some View {
if let person = person {
return AnyView(
VStack {
Text("Name:")
Text(person.name)
}
)
} else {
return AnyView(EmptyView())
}
}
}
Run Code Online (Sandbox Code Playgroud)
e) 使用封装 if-let 条件的辅助 View 类型,示例实现:IfLet/ OptionalView;也可以作为函数使用ifLet。
| 归档时间: |
|
| 查看次数: |
6942 次 |
| 最近记录: |