我在这里重新创建了一个最小的可复制示例。我使用的是Xcode 13 beta 5.
在我的项目中,我正在呈现一个带有List和ForEach循环的记分卡列表。我正在使用swipeactions来删除记分卡。在我删除记分卡之后,然后添加一个记分卡,这个列表在边缘被渲染为额外的填充或listRowInset。
同样,在ContentView中,当记分卡数组为空时,我使用if/else语句来呈现消息。我想这就是bug发生的地方,但我真的不知道如何解决它。
列表应该是这样的…
列表的正确呈现
和下面是意想不到的,有bug的渲染…
删除记分卡并添加新记分卡后呈现不正确
要重新创建该bug,首先通过从后缘滑动删除记分卡,然后单击顶部的添加记分卡,您将看到记分卡前沿的额外空白。我将附上下面的代码…提前感谢您的帮助!
import SwiftUI
struct ContentView: View {
@State var scorecards = [
Scorecard(date: Date()),
]
var sortedScorecards: [Scorecard] {
get {
scorecards.sorted {
$0.date > $1.date
}
}
set {
scorecards = newValue
}
}
var body: some View {
VStack {
Button {
scorecards = [
Scorecard(date: Date()),
]
} label: {
Text("Add Scorecard")
}
if scorecards.count < 1 {
Spacer()
HStack{
Spacer()
Text("No previous scorecards. Start a scorecard!")
.font(.headline)
.padding(20)
.multilineTextAlignment(.center)
Spacer()
}
Spacer()
} else {
List {
ForEach(sortedScorecards, id:.self) { scorecard in
if #available(iOS 15.0, *) {
Button {
} label: {
Card(scorecard: scorecard)
}.buttonStyle(.plain)
.listRowInsets(.init(top:7.5,
leading:0,
bottom:7.5,
trailing:0))
.swipeActions(edge: .trailing, allowsFullSwipe: false) {
Button("Delete Scorecard", role: .destructive) {
deleteScorecard(scorecard: scorecard)
}
}
} else {
// Fallback on earlier versions
}
}
}
.onAppear {
UITableView.appearance().backgroundColor = .black
}
}
}
}
func deleteScorecard(scorecard:Scorecard) {
scorecards = scorecards.filter{$0.id != scorecard.id}
}
}
struct Card: View {
var scorecard:Scorecard
func scorecardDate(date:Date) -> String {
let formatter = DateFormatter()
formatter.dateStyle = .short
formatter.timeStyle = .short
return formatter.string(from: date)
}
var body:some View {
ZStack {
Rectangle()
.foregroundColor(Color.blue)
.frame(height: 25)
Text(scorecardDate(date:scorecard.date))
}
}
}
struct Scorecard:Hashable {
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
var id = UUID().uuidString
var date:Date
}
似乎与if/else
语句有关。当List
从视图层次结构中删除然后添加回来时,insert似乎变得混乱。
插入的数量对我来说很熟悉——就像如果在前面有一个删除按钮应该插入的数量一样。所以,根据直觉,我添加了一个显式调用,将编辑模式设置为.inactive
。这似乎行得通。
在视图的顶部添加:
@Environment(.editMode) private var editMode
然后,在您的deleteScorecard(scorecard:Scorecard)
中:
func deleteScorecard(scorecard:Scorecard) {
scorecards = scorecards.filter{$0.id != scorecard.id}
editMode?.wrappedValue = .inactive //<-- here
}
这似乎明确地关闭了编辑模式,然后避免了当List
被添加回视图层次结构时的错误。
Update - secondary solution.
这是我想出的另一个解决方案,因为我的代码与你的示例代码工作,但不是与你的应用程序。在这个版本中,List
被包含在整个视图层次结构中,但框架被设置为0
的高度,如果没有任何项目。由于你所设置的背景颜色,可能会有副作用,这也是我最初没有包括这个的原因之一,但由于最初的解决方案并不理想,现在值得包括:
var body: some View {
VStack {
Button {
scorecards = [
Scorecard(date: Date()),
]
} label: {
Text("Add Scorecard")
}
if scorecards.count < 1 {
VStack {
Spacer()
HStack{
Spacer()
Text("No previous scorecards. Start a scorecard!")
.font(.headline)
.padding(20)
.multilineTextAlignment(.center)
Spacer()
}
Spacer()
}
}
List {
ForEach(sortedScorecards, id:.self) { scorecard in
if #available(iOS 15.0, *) {
Button {
} label: {
Card(scorecard: scorecard)
}.buttonStyle(.plain)
.listRowInsets(.init(top:7.5,
leading:0,
bottom:7.5,
trailing:0))
.swipeActions(edge: .trailing, allowsFullSwipe: false) {
Button("Delete Scorecard", role: .destructive) {
deleteScorecard(scorecard: scorecard)
}
}
} else {
// Fallback on earlier versions
}
}
}
.frame(maxHeight: scorecards.count == 0 ? 0 : .infinity)
.onAppear {
UITableView.appearance().backgroundColor = .black
}
}
}