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

SwiftUI实现仿备忘录App带确认弹窗的删除功能及按钮宽度问题

SwiftUI实现备忘录风格删除交互:解决删除按钮无法铺满单元格宽度问题

问题描述

尝试在SwiftUI中实现苹果备忘录(Notes)App的删除笔记交互逻辑,当前代码已实现侧滑删除按钮,但存在删除按钮无法铺满单元格宽度的问题,效果如下:

效果演示

当前代码:

import SwiftUI

struct ItemStore {
    var items: [String]
}
struct ContentView: View {
    let itemStore = ItemStore(items: [
        "Hi",
        "Hello"
    ])
    @State var showingAlert = false

    var body: some View {
        List {
            ForEach(itemStore.items, id: \.self) { item in
                Text("Item: \(item)")
                    .swipeActions() {
                        Button {
                            withAnimation { showingAlert.toggle() }
                        } label: {
                            Label("Delete", systemImage: "trash")
                        }
                    }
                    .tint(.red)
            }
        }
        .alert("Important message", isPresented: $showingAlert) {
            Button("First") { }
            Button("Second") { }
        }
    }
}

解决方案

要实现类似备忘录的全屏侧滑删除按钮,需做两个关键修改:

  1. 使用.fullSwipeAction替代普通的.swipeActions,这是SwiftUI专门用于实现全屏侧滑触发的动作API
  2. 修正数据可变性,确保能实际删除列表项;同时为每个列表项绑定对应删除确认逻辑

修改后的完整代码:

import SwiftUI

struct ItemStore {
    var items: [String]
}

struct ContentView: View {
    // 将itemStore改为@State,允许修改列表数据
    @State private var itemStore = ItemStore(items: [
        "Hi",
        "Hello"
    ])
    // 用可选值存储当前要删除的item,避免多个item共用同一个alert状态
    @State private var itemToDelete: String?

    var body: some View {
        List {
            ForEach(itemStore.items, id: \.self) { item in
                Text("Item: \(item)")
                    // 使用fullSwipeAction实现全屏侧滑删除
                    .fullSwipeAction(edge: .trailing) {
                        // 触发删除确认弹窗
                        itemToDelete = item
                    } label: {
                        Label("Delete", systemImage: "trash")
                    }
                    .tint(.red)
            }
        }
        // 绑定到当前要删除的item,只有当itemToDelete不为空时才显示弹窗
        .alert("确定要删除这条笔记吗?", isPresented: $itemToDelete.isPresent()) {
            Button("取消", role: .cancel) {
                itemToDelete = nil
            }
            Button("删除", role: .destructive) {
                if let item = itemToDelete {
                    // 执行删除操作
                    itemStore.items.removeAll { $0 == item }
                    itemToDelete = nil
                }
            }
        }
    }
}

// 扩展Optional,方便绑定alert的isPresented
extension Optional {
    func isPresent() -> Binding<Bool> {
        Binding(
            get: { self != nil },
            set: { if !$0 { self = nil } }
        )
    }
}

代码说明

  • .fullSwipeAction(edge: .trailing):该API会创建铺满单元格宽度的侧滑动作按钮,完全匹配备忘录App的交互效果
  • 将itemStore改为@State:原let常量无法修改数据,改为@State后可实时更新列表内容
  • 使用itemToDelete可选值:避免所有列表项共用同一个showingAlert状态,确保弹窗只对应当前要删除的项
  • 自定义isPresent()绑定:简化可选值到Bool的转换,让alert显示逻辑更清晰

内容的提问来源于stack exchange,提问作者Javier Roberto

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 12:50:14