You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过代码还原SwiftUI List单元格的滑动操作?

后台时重置SwiftUI List单元格滑动状态

可行,有两种主流实现方式,分别适配纯SwiftUI场景和需要底层UIKit控制的场景:

方法一:纯SwiftUI状态驱动重置

通过给单元格附加可变标识,触发视图重绘来自动收起滑动操作:

struct ContentView: View {
    @Environment(\.scenePhase) private var scenePhase
    @State private var items = ["Item 1", "Item 2", "Item 3"]
    @State private var resetSwipeTrigger = false

    var body: some View {
        List {
            ForEach(items, id: \.self) { item in
                Text(item)
                    .swipeActions(edge: .trailing) {
                        Button(role: .destructive) {
                            // 执行删除逻辑
                        } label: {
                            Label("删除", systemImage: "trash")
                        }
                    }
                    .swipeActions(edge: .leading) {
                        Button {
                            // 执行标记逻辑
                        } label: {
                            Label("标记", systemImage: "checkmark")
                        }
                    }
                    // 利用id变化触发单元格重绘,自动收起滑动状态
                    .id("\(item)-\(resetSwipeTrigger)")
            }
        }
        .onChange(of: scenePhase) { newPhase in
            if newPhase == .background {
                resetSwipeTrigger.toggle()
            }
        }
    }
}

原理:当应用进入后台时,切换resetSwipeTrigger状态,SwiftUI会识别到单元格的id发生变化,重新渲染单元格,此时滑动展开的操作按钮会自动收起。

方法二:UIKit底层控制(更精准)

直接操作UITableView的API,主动收起滑动的行操作:

struct ResetableSwipeList: UIViewRepresentable {
    var items: [String]
    var onDelete: (String) -> Void
    var onMark: (String) -> Void

    func makeUIView(context: Context) -> UITableView {
        let tableView = UITableView()
        tableView.delegate = context.coordinator
        tableView.dataSource = context.coordinator
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "SwipeCell")
        
        // 监听应用进入后台的通知
        NotificationCenter.default.addObserver(
            context.coordinator,
            selector: #selector(Coordinator.resetAllSwipeActions),
            name: UIApplication.didEnterBackgroundNotification,
            object: nil
        )
        return tableView
    }

    func updateUIView(_ uiView: UITableView, context: Context) {
        uiView.reloadData()
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    class Coordinator: NSObject, UITableViewDelegate, UITableViewDataSource {
        private let parent: ResetableSwipeList

        init(_ parent: ResetableSwipeList) {
            self.parent = parent
        }

        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            parent.items.count
        }

        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "SwipeCell", for: indexPath)
            cell.textLabel?.text = parent.items[indexPath.row]
            return cell
        }

        // 配置右侧滑动操作
        func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
            let deleteAction = UIContextualAction(style: .destructive, title: "删除") { [weak self] _, _, completion in
                guard let self = self else { return }
                self.parent.onDelete(self.parent.items[indexPath.row])
                completion(true)
            }
            deleteAction.image = UIImage(systemName: "trash")
            return UISwipeActionsConfiguration(actions: [deleteAction])
        }

        // 配置左侧滑动操作
        func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
            let markAction = UIContextualAction(style: .normal, title: "标记") { [weak self] _, _, completion in
                guard let self = self else { return }
                self.parent.onMark(self.parent.items[indexPath.row])
                completion(true)
            }
            markAction.image = UIImage(systemName: "checkmark")
            markAction.backgroundColor = .systemGreen
            return UISwipeActionsConfiguration(actions: [markAction])
        }

        // 重置所有滑动状态
        @objc func resetAllSwipeActions() {
            guard let visibleIndexPaths = tableView.indexPathsForVisibleRows else { return }
            for indexPath in visibleIndexPaths {
                tableView.closeRowActions(at: indexPath)
            }
        }
    }
}

原理:通过UIViewRepresentable封装UITableView,监听后台通知后,调用tableView.closeRowActions(at:)主动收起每个可见单元格的滑动操作,这种方式可以精准控制状态,不会触发额外的视图重绘。

内容的提问来源于stack exchange,提问作者Reinhard Männer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 06:45:35