Ben*_*eil 11 swift swiftui swift5.1
如何根据条件添加附加属性?
使用下面的代码,我得到了错误 Cannot assign value of type 'some View' (result of 'Self.overlay(_:alignment:)') to type 'some View' (result of 'Self.onTapGesture(count:perform:)')
import SwiftUI
struct ConditionalProperty: View {
@State var overlay: Bool
var body: some View {
var view = Image(systemName: "photo")
.resizable()
.onTapGesture(count: 2, perform: self.tap)
if self.overlay {
view = view.overlay(Circle().foregroundColor(Color.red))
}
return view
}
func tap() {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
ccw*_*den 18
感谢这篇文章,我找到了一个界面非常简单的选项:
Text("Hello")
.if(shouldBeRed) { $0.foregroundColor(.red) }
Run Code Online (Sandbox Code Playgroud)
由这个扩展启用:
extension View {
@ViewBuilder
func `if`<Transform: View>(_ condition: Bool, transform: (Self) -> Transform) -> some View {
if condition { transform(self) }
else { self }
}
}
Run Code Online (Sandbox Code Playgroud)
这是一篇很棒的博客文章,其中包含有关条件修饰符的其他提示:https : //fivestars.blog/swiftui/conditional-modifiers.html
Dam*_*aux 13
Rob Mayoff已经很好地解释了为什么会出现这种行为并提出了两种解决方案(透明叠加或使用AnyView)。第三种更优雅的方法是使用 _ConditionalContent。
一种简单的创建方法_ConditionalContent是if else在组或堆栈中编写语句。这是使用组的示例:
import SwiftUI
struct ConditionalProperty: View {
@State var overlay: Bool
var body: some View {
Group {
if overlay {
base.overlay(Circle().foregroundColor(Color.red))
} else {
base
}
}
}
var base: some View {
Image("photo")
.resizable()
.onTapGesture(count: 2, perform: self.tap)
}
func tap() {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
rob*_*off 10
在 SwiftUI 术语中,您不是在添加属性。您正在添加修饰符。
这里的问题是,在 SwiftUI 中,每个修饰符都返回一个取决于它正在修改的内容的类型。
var view = Image(systemName: "photo")
.resizable()
.onTapGesture(count: 2, perform: self.tap)
// view has some deduced type like GestureModifier<SizeModifier<Image>>
if self.overlay {
let newView = view.overlay(Circle().foregroundColor(Color.red))
// newView has a different type than view, something like
// OverlayModifier<GestureModifier<SizeModifier<Image>>>
}
Run Code Online (Sandbox Code Playgroud)
由于newView具有与 不同的类型view,因此您不能只分配view = newView.
解决此问题的一种方法是始终使用overlay修饰符,但在您不希望叠加层可见时使其透明:
var body: some View {
return Image(systemName: "photo")
.resizable()
.onTapGesture(count: 2, perform: self.tap)
.overlay(Circle().foregroundColor(overlay ? .red : .clear))
}
Run Code Online (Sandbox Code Playgroud)
处理它的另一种方法是使用类型橡皮擦AnyView:
var body: some View {
let view = Image(systemName: "photo")
.resizable()
.onTapGesture(count: 2, perform: self.tap)
if overlay {
return AnyView(view.overlay(Circle().foregroundColor(.red)))
} else {
return AnyView(view)
}
}
Run Code Online (Sandbox Code Playgroud)
我从 Apple 工程师那里看到的建议是避免使用,AnyView因为它比使用完全类型化的视图效率低。例如,这条推文和这条推文。
if - else仅当您别无选择时才使用包括表达式的条件修饰符。条件修饰符的巨大缺点是它们创建新视图,这可能会导致意外行为,例如它们会破坏动画。
几乎所有修饰符都接受不改变nil的值,因此如果可能,请始终使用类似的值
@State var overlay: Bool
var body: some View {
Image(systemName: "photo")
.resizable()
.overlay(overlay ? Circle().foregroundColor(Color.red) : nil)
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10288 次 |
| 最近记录: |