在 ForEach 视图中使用 Conditional 对每个视图应用不同的效果
Posted
技术标签:
【中文标题】在 ForEach 视图中使用 Conditional 对每个视图应用不同的效果【英文标题】:Using Conditional Inside a ForEach view to apply different effects to each view 【发布时间】:2020-05-18 20:39:51 【问题描述】:我正在尝试呈现数组中的项目列表。数组项是具有字符串和整数的结构。我希望数组中整数大于 0 的项目左对齐,等于 0 居中对齐,小于 0 右对齐。将来我希望能够应用其他一些差异,但现在我只需要不同的对齐方式。
我曾尝试使用 ForEach 视图循环遍历数组中的项目,并使用 if else 语句尝试两种不同的显示方式,但我收到一个错误,即 () 无法适应“查看”。
编辑:添加确切的错误消息:Type '()' cannot conform to 'View'; only struct/enum/class types can conform to protocols
这是我在 ForEach 中循环的结构:
struct PreviouslyPlayedData: Hashable
let text: String
let speaker: Int
这是我现在设置的 ForEach,它给出了错误。
ForEach(previouslyPlayed, id: \.self) data in
if (data.speaker == 0)
Text(data.text)
.frame(width: 300, height: nil, alignment: .center)
else
Text(data.text)
.frame(width: 300, height: nil, alignment: .leading)
【问题讨论】:
它给出了什么错误? 类型 '()' 不能符合 'View';只有结构/枚举/类类型可以符合协议 【参考方案1】:您不能在ForEach
中使用条件。
SwiftUI 在幕后做了很多工作,它只是希望您的 ContentView
中只包含一种非常特定类型的 View。它不关心哪种类型的视图(因此是-> some View
),但它确实关心只能返回一种类型。虽然有时你可以保证在你的条件句中,Swift 不能为你完全理解它。
您有多种解决方法。如果你的逻辑比较简单,不需要修改太多,可以使用三元运算符来切换样式:
ForEach(previouslyPlayed, id: \.self) data in
Text(data.text)
.frame(width: 300, height: nil, alignment: data.speaker == 0 ? .center : .leading)
【讨论】:
【参考方案2】:另一种方法是在自己的视图中显示每个项目,它可以根据项目处理对齐,并使用主内容视图显示列表:
例如:
import SwiftUI
struct PreviouslyPlayedData: Identifiable
let id = UUID() // To make it easier to use in lists
let text: String
let speaker: Int
static var previewItems: [PreviouslyPlayedData]
[PreviouslyPlayedData(text: "First", speaker: -1),
PreviouslyPlayedData(text: "Second", speaker: -1),
PreviouslyPlayedData(text: "third", speaker: 0),
PreviouslyPlayedData(text: "Fourth", speaker: 1),
PreviouslyPlayedData(text: "Fifth", speaker: -1),
PreviouslyPlayedData(text: "Sixth", speaker: 2),
]
struct ContentView: View
var items = PreviouslyPlayedData.previewItems
var body: some View
List(items) item in
DataView(item: item)
struct DataView: View
let item: PreviouslyPlayedData
var itemAlignment: Alignment
if item.speaker < 0
return .leading
else if item.speaker == 0
return .center
else
return .trailing
var body: some View
Text(item.text).frame(maxWidth: .infinity, alignment: itemAlignment)
struct ContentView_Previews: PreviewProvider
static var previews: some View
ContentView()
看起来像:
【讨论】:
以上是关于在 ForEach 视图中使用 Conditional 对每个视图应用不同的效果的主要内容,如果未能解决你的问题,请参考以下文章