swift - Swiftui listRowInsets 添加到空数组时会发生意外更改
问题描述
我在这里重新创建了一个最小的可重现示例。我正在使用 Xcode 13 beta 5。
在我的项目中,我使用 List 和 ForEach 循环呈现记分卡列表。我正在使用滑动操作来删除记分卡。在我删除记分卡,然后添加记分卡后,列表会在前缘使用额外的填充或 listRowInset 呈现。
此外,在 ContentView 中,我使用 if/else 语句在记分卡数组为空时呈现消息。我在想这是错误发生的地方,但真的不知道如何解决它。
这是列表的外观...
下面是意想不到的错误渲染......
要重新创建错误,首先通过从后缘滑动删除记分卡,然后单击顶部的添加记分卡,您将在记分卡的前缘看到额外的空白。我将附上下面的代码......提前感谢您的帮助!
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
从视图层次结构中删除然后重新添加时,插图似乎搞砸了。
插入的数量对我来说看起来很熟悉——就像在前导边有一个删除按钮时应该插入的数量一样。所以,凭直觉,我添加了一个显式调用来将编辑模式设置为.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
其添加回视图层次结构时避免了该错误。
更新——次要解决方案。
这是我想出的另一个解决方案,因为我的代码适用于您的示例代码,但不适用于您的应用程序。在此版本中,始终包含在视图层次结构中,但如果没有任何项目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
}
}
}
推荐阅读
- docker - Spring Boot 消耗太多内存
- laravel - 嵌套资源上的 Laravel 自定义控制器功能
- c# - 使用 LinqToTwitter 与 Twitter direct_messages/events 进行异步和等待
- python-3.x - 添加 tkinter 接口后无法运行我的应用程序
- python - PySpark - 将列表作为参数传递给 UDF + 迭代数据框列添加
- reporting-services - SSRS:参数值的组合框在预览中不起作用
- c++ - 必须在 C++ 中将 c_str 用于 strchr 吗?
- azure - 从虚拟网关中删除点到站点
- c# - WPF XAML 数据触发器内容模板
- javascript - 在 Firebase 中处理用户的在线和离线状态