iOS 26中SwiftUI List绑定confirmationDialog弹窗位置异常问询
问题解答:SwiftUI List绑定confirmationDialog弹窗不靠近行是否正常
结论
这种弹窗不靠近待删除行的情况是正常行为。
原因解释
你当前的代码把confirmationDialog直接附加在了整个List视图上,而非触发删除操作的具体列表行。在iOS 16+(你提到的iOS26应该是笔误)中,confirmationDialog的弹出锚点由它所绑定的父视图决定——绑定到整个List时,弹窗会以List的整体区域为锚点(通常是屏幕中间或List中心),自然不会靠近具体的待删除行。
另外补充:iOS15及更早版本中confirmationDialog始终显示在底部,是因为当时该组件还没有popover展示特性,iOS16才引入了基于锚点的popover样式,但锚点完全由你绑定的父视图决定。
解决方案:让弹窗绑定到具体列表行
要实现弹窗靠近待删除行的效果,需要把confirmationDialog移到ForEach内部的列表行视图上,同时调整状态变量跟踪目标行,配合标准的列表滑动删除交互:
修改后的代码示例:
import SwiftUI struct AlertTestingView: View { @State private var items = ["Task 1", "Task 2", "Task 3", "Task 4"] // 改为跟踪具体要删除的条目,而非IndexSet @State private var itemToDelete: String? var body: some View { NavigationStack { List { ForEach(items, id: \.self) { item in Text(item) .swipeActions(edge: .trailing) { Button("Delete", role: .destructive) { itemToDelete = item } } // 将confirmationDialog绑定到当前列表行 .confirmationDialog( "Are you sure you want to delete this?", isPresented: .constant(itemToDelete == item), titleVisibility: .visible, presenting: itemToDelete ) { _ in Button("Delete", role: .destructive) { if let index = items.firstIndex(of: item) { items.remove(at: index) } itemToDelete = nil } Button("Cancel", role: .cancel) { itemToDelete = nil } } message: { _ in Text("This action cannot be undone.") } } } .navigationTitle("iOS 16 Testing") } } }
关键调整说明
- 将
confirmationDialog附加到每个列表行的Text视图上,弹窗会自动以当前行为锚点弹出,贴合交互触发位置。 - 使用
presenting参数传递待删除条目,替代原有的isPresented绑定,更精准控制弹窗的显示逻辑。 - 配合
swipeActions实现列表滑动删除的标准交互,符合iOS用户的操作习惯。
内容的提问来源于stack exchange,提问作者fs_tigre
相关产品推荐
相关产品推荐

