SwiftUI条件修饰符添加



基于bool,我想在SwiftUI中添加一个文本修饰符。

理想情况下,我会这样做:

Text(text)
if(true) {
.bold()
}
.foregroundColor(Color.black)
.frame(alignment: .leading)

抛出错误——唯一的"不复杂的";我能想到的另一种选择是,根据bool值,创建2个不同的文本。然而,这会导致大量的代码重复。我能做什么呢?

我还尝试将Text声明为let变量,以便稍后在代码中访问它,但是这会阻止元素显示。

可能的设置如下:

let title = Text("text")
.foregroundColor(Color.black)

,然后在正文中做

if(true) {
title
.bold()
}

然而,如果我在声明中再添加一个修饰符,它告诉我Property definition has inferred type 'some View', involving the 'some' return type of another declaration

苹果不推荐使用条件修饰语,因为一旦条件改变,就会破坏视图的身份。对于您的用例,一个简单的替代方法是三元操作符:

Text(text)
.fontWeight(condition ? .bold : .regular)
.foregroundColor(Color.black)

与Florian S所说的一样,您应该使用三元格式,因为视图修饰符上的内联条件可能会导致许多问题,但是……它们有时也很有用,所以如果你想在视图修饰符上使用内联条件操作,请这样做。

添加一些扩展到视图..你不需要这两种方法,但根据你想要使用它的方式,每种方法都有自己的优势

extension View {

@ViewBuilder func `if`<Content: View>(_ condition: Bool, transform: (Self) -> Content) -> some View {
if (condition) {
transform(self)
} else {
self
}
}

@ViewBuilder func `ifInline`<Content: View>(_ condition: @autoclosure () -> Bool, transform: (Self) -> Content) -> some View {
if condition() {
transform(self)
} else {
self
}
}
}

然后,在您想使用扩展名with的视图上执行如下操作

ForEach(values: self.multiDevice ? devices : device) { device in
Group {
ForEach(values: ColorScheme.allCases) { scheme in
self.viewToPreview
.background(Color.backgroundColor)
.colorScheme(scheme)
.previewDevice(PreviewDevice(rawValue: device))
.previewDisplayName("(displayName) - (scheme.previewName) - (device)")
.if(self.wrapped) { view in
view.previewLayout(.sizeThatFits)
}
}
}
}

使用第二个扩展名'。if'会变成'. ifinline '.

一个小提示,这个用例来自我在我的项目中创建的GenPreviews类,它可以更容易地在各种设备和配色方案上显示画布预览,我可以从提供程序中提供一个名称和一些我可以传递的工具,以显示一个设备或多个我包含的两个选项列表,以及在设备预览上包装或显示视图。

我提出这个问题的原因是因为这个用例不仅没有在生产运行时中使用,而且在编译发布时甚至没有包含…这可以追溯到我的第一个声明,我同意Florian S.我以前在运行代码的视图修饰符上使用了内联条件,但这不是很好的实践,除非情况需要并允许,否则不应该这样做。对于您的情况,使用三元操作符将是最好的方法。

我的两分钱,希望能帮助到别人。(我来这里是为了看看关于…)我确实读过DOES劝阻修饰符,所以一个完全不同的方法可以是给别人的提示。

我需要在许多地方隐藏/显示搜索,而不是弄得太乱。

//  Created by ing.conti on 19/08/23.
//
import SwiftUI
struct ContentView: View {
@State private var searchText = ""
@State private var showIt = true
var body: some View {
NavigationStack {
Text("typed: (searchText)")
.onChange(of: self.searchText, perform: { newValue in
if self.searchText.count>5{
self.showIt.toggle()
}
})
.navigationTitle("Hide/ Show Sample")

Spacer()
Button( self.showIt ?  "Hide" : "Show") {
self.showIt.toggle()
}.padding(4).border(.blue)
}
.eventuallySearchable(with: $searchText, showIt: self.showIt)
}
}

// Modifier:
struct SearchText: ViewModifier {
@Binding var searchText: String
let showIt: Bool

func body(content: Content) -> some View {
if showIt{
content
.searchable(text: $searchText)
}else{
content
}
}
}

public extension View {
func eventuallySearchable(with text: Binding<String>, showIt: Bool) -> some View {
modifier(SearchText(searchText: text, showIt: showIt))
}
}

最新更新