SwiftUI swipeActions 重新加载导致前导空白 space 和滑动中断
SwiftUI swipeActions reload results in leading blank space and broken swipe
我正在尝试使用 swipeActions SwiftUI 修改器设置,如下面的代码所示,但滑动操作被禁用,如此 gif 所示:
struct ContentView: View {
@ObservedObject var viewModel: ViewModel
var body: some View {
if viewModel.items.count > 0 {
ZStack {
List {
ForEach(viewModel.items, id: \.self) { item in
Text(item)
.swipeActions {
Button {
viewModel.removeAction(item: item)
} label: {
Text("Remove")
}
.tint(.orange)
}
}
}
}
} else {
ProgressView()
.foregroundColor(.accentColor)
.scaleEffect(2)
}
}
在第一次滑动后的视图模型中,我将从 API 重新加载列表(示例代码只是模拟延迟):
extension ContentView {
class ViewModel: ObservableObject {
@Published var items: [String]
init(items: [String]) {
self.items = items
}
func removeAction(item: String) {
if let index = items.firstIndex(where: { [=12=] == item }) {
items.remove(at: index)
}
let itemsSaved = items
items = []
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
self.items = itemsSaved
}
}
}
预期行为:重新加载的行在每行的开头没有 space 视图,并且可以像以前一样滑动行。
实际行为:每行在行的开头都有一个space视图,您不能像以前那样滑动行。
我还创建了一个示例项目:code and additional video。
知道是否有解决方法吗?
谢谢。
我仍然不确定为什么您的实现会导致此行为,除了您完全在两个单独的视图之间切换(Zstack
与 ProgressView
)。我怀疑来回更改只是将 List
置于某种奇怪的状态。但是,修复很简单;将条件放在 ZStack
:
中
struct ContentView: View {
@ObservedObject var viewModel: ViewModel
var body: some View {
ZStack {
// Move the conitional inside of the ZStack.
// Always use .isEmpty for this sort of test. Faster and
// less resources than count
if !viewModel.items.isEmpty {
List {
// I made Item an Identifiable struct. Deleting items
// identified as .self can lead to issues in a ForEach
ForEach(viewModel.items) { item in
Text(item.name)
.swipeActions {
Button {
viewModel.removeAction(item: item)
} label: {
Text("Remove")
}
.tint(.orange)
}
}
}
} else {
Text("Progress View")
}
}
}
}
extension ContentView {
class ViewModel: ObservableObject {
@Published var items: [Item]
init(items: [Item]) {
self.items = items
}
func removeAction(item: Item) {
if let index = items.firstIndex(where: { [=10=] == item }) {
items.remove(at: index)
}
let itemsSaved = items
items = []
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
self.items = itemsSaved
}
}
}
}
// I made this as a data model.
struct Item: Identifiable, Hashable {
var id = UUID()
var name: String
}
我正在尝试使用 swipeActions SwiftUI 修改器设置,如下面的代码所示,但滑动操作被禁用,如此 gif 所示:
struct ContentView: View {
@ObservedObject var viewModel: ViewModel
var body: some View {
if viewModel.items.count > 0 {
ZStack {
List {
ForEach(viewModel.items, id: \.self) { item in
Text(item)
.swipeActions {
Button {
viewModel.removeAction(item: item)
} label: {
Text("Remove")
}
.tint(.orange)
}
}
}
}
} else {
ProgressView()
.foregroundColor(.accentColor)
.scaleEffect(2)
}
}
在第一次滑动后的视图模型中,我将从 API 重新加载列表(示例代码只是模拟延迟):
extension ContentView {
class ViewModel: ObservableObject {
@Published var items: [String]
init(items: [String]) {
self.items = items
}
func removeAction(item: String) {
if let index = items.firstIndex(where: { [=12=] == item }) {
items.remove(at: index)
}
let itemsSaved = items
items = []
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
self.items = itemsSaved
}
}
}
预期行为:重新加载的行在每行的开头没有 space 视图,并且可以像以前一样滑动行。
实际行为:每行在行的开头都有一个space视图,您不能像以前那样滑动行。
我还创建了一个示例项目:code and additional video。
知道是否有解决方法吗?
谢谢。
我仍然不确定为什么您的实现会导致此行为,除了您完全在两个单独的视图之间切换(Zstack
与 ProgressView
)。我怀疑来回更改只是将 List
置于某种奇怪的状态。但是,修复很简单;将条件放在 ZStack
:
struct ContentView: View {
@ObservedObject var viewModel: ViewModel
var body: some View {
ZStack {
// Move the conitional inside of the ZStack.
// Always use .isEmpty for this sort of test. Faster and
// less resources than count
if !viewModel.items.isEmpty {
List {
// I made Item an Identifiable struct. Deleting items
// identified as .self can lead to issues in a ForEach
ForEach(viewModel.items) { item in
Text(item.name)
.swipeActions {
Button {
viewModel.removeAction(item: item)
} label: {
Text("Remove")
}
.tint(.orange)
}
}
}
} else {
Text("Progress View")
}
}
}
}
extension ContentView {
class ViewModel: ObservableObject {
@Published var items: [Item]
init(items: [Item]) {
self.items = items
}
func removeAction(item: Item) {
if let index = items.firstIndex(where: { [=10=] == item }) {
items.remove(at: index)
}
let itemsSaved = items
items = []
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
self.items = itemsSaved
}
}
}
}
// I made this as a data model.
struct Item: Identifiable, Hashable {
var id = UUID()
var name: String
}