问题描述
在测试辅助功能accessibilityDifferentiateWithoutColor时,下面的代码报错:
@Environment(\.accessibilityDifferentiateWithoutColor) var differentiateWithoutColor
RoundedRectangle(cornerRadius: 10)
.overlay(
differentiateWithoutColor ?
Text(status == "active" ? "启用" : "禁用")
.foregroundColor(.white) : EmptyView()
)
报错内容为:
Result values in '? :' expression have mismatching types 'Text' and 'EmptyView'
问题原因
SwiftUI 中的 ? : 三元表达式要求返回的两个值类型必须相同。上述代码中,Text 和 EmptyView 是不同的类型,因此编译器会报错。
要修复此问题,可以使用一个封装在 AnyView 中的类型擦除方法,或者直接通过 Group 或条件视图来解决。
解决方法
解决方案 1:使用类型擦除 (AnyView)
@Environment(\.accessibilityDifferentiateWithoutColor) var differentiateWithoutColor
RoundedRectangle(cornerRadius: 10)
.overlay(
differentiateWithoutColor ?
AnyView(Text(status == "active" ? "启用" : "禁用")
.foregroundColor(.white)) : AnyView(EmptyView())
)
解决方案 2:使用 Group 包装多个视图
Group 会将不同类型的视图包裹成一个视图组合,保证类型一致性:
@Environment(\.accessibilityDifferentiateWithoutColor) var differentiateWithoutColor
RoundedRectangle(cornerRadius: 10)
.overlay(
Group {
if differentiateWithoutColor {
Text(status == "active" ? "启用" : "禁用")
.foregroundColor(.white)
}
}
)
有问题的解决方案 3:使用条件视图
注意,如果尝试直接使用条件语句进行替换,会产生报错。下面是关于报错原因的分析,以便进一步了解这一解决方案。
在 SwiftUI 中,直接通过条件语句(if)来动态添加视图,可能会报错:
@Environment(\.accessibilityDifferentiateWithoutColor) var differentiateWithoutColor
RoundedRectangle(cornerRadius: 10)
.overlay(
if differentiateWithoutColor {
Text(status == "active" ? "启用" : "禁用")
.foregroundColor(.white)
}
)
需要注意的是,这里的if会报错:
'if' may only be used as expression in return, throw, or as the source of an assignment
'if' must have an unconditional 'else' to be used as expression
原因为:在 SwiftUI 中,.overlay() 是一个修饰符,需要一个返回视图的闭包,而不能直接接受条件语句 if。因此,当您在 .overlay() 中使用条件语句时,必须提供默认视图,例如 EmptyView(),以保证返回值始终有效。
.overlay {
if differentiateWithoutColor {
Text(status == "active" ? "启用" : "禁用")
.foregroundColor(.white)
} else {
EmptyView()
}
}
当尝试使用if返回EmptyView()时仍然会报错:
Branches have mismatching types 'Text' and 'EmptyView'
原因为:SwiftUI 中的 .overlay 方法要求闭包返回一个视图,而 if … else 的分支必须返回相同的类型,但 Text 和 EmptyView 是不同的类型。因此,SwiftUI 无法推断视图类型。
因此,应该只考虑前面的两种正确的解决方案。