英文:
How to show multiple kinds of ConfirmationDialog?
问题
与表格不同,ConfirmationDialog没有带有参数item: Binding<Item?>的初始化函数,唯一的函数是isPresented: Binding<Bool>,用于控制标题和按钮。
例如,在一个视图中,需要确认三种**种类(而不是单个项目)**的删除操作,每种操作需要不同的标题和按钮。
我不想将其分为3个视图或使用3个isPresented绑定。有什么建议吗?
英文:
Unlike sheet, ConfirmationDialog have no init func with parameter item: Binding<Item?>, the only one isPresented: Binding<Bool> to control title and buttons.
for example, in one view, there are 3 kinds(NOT pieces) of deletion actions need to confirm with different title and buttons for each.
I don't want to separate to 3 views or 3 isPresented bindings. any suggestion?
答案1
得分: 0
是的,我们可以使用 "presenting data: T?" 来识别 ConfirmationDialog 的类型,就像 sheet 的 Binding<Item?> 一样。我认为苹果设计 "isPresented: Binding
以下是一个示例(还可以查看有关 ConfirmationDialog 的全部代码):
enum ConfirmationID {
case test1
case test2
case test3
var id: ConfirmationID { self }
}
struct ConfirmationItem: Identifiable {
var id: ConfirmationID
var item: String
}
struct ConfirmationDialog0: View {
@State private var messages: [Int] = (0..<5).map { $0 }
@State private var isPresented: Bool = false
@State private var confirmationItem: ConfirmationItem?
var body: some View {
NavigationView {
GeometryReader { proxy in
ScrollView {
HStack {
Button("test 1") {
confirmationItem = ConfirmationItem(id: .test1, item: "test 1")
isPresented = true
}
Button("test 2") {
confirmationItem = ConfirmationItem(id: .test2, item: "test 2")
isPresented = true
}
Button("test 3") {
confirmationItem = ConfirmationItem(id: .test3, item: "test 3")
isPresented = true
}
}
List {
ForEach(messages, id: \.self) { message in
itemView0(message: message) { _ in
withAnimation {
messages = messages.filter { $0 != message }
}
}
}
}
.frame(height: proxy.size.height)
}
}
.navigationTitle("WRONG if .destructive!")
.confirmationDialog("CONFIRM", isPresented: $isPresented, titleVisibility: .visible, presenting: confirmationItem, actions: confirmationDialogActionsView, message: confirmationDialogMassageView)
}
}
@ViewBuilder
func confirmationDialogActionsView(item: ConfirmationItem) -> some View {
switch item.id {
case .test1:
Button(action: {}) {
Text("do with item \(item.item): ") + Text(Image(systemName: "star")) + Text(" World!")
}
case .test2:
Button("delete with item \(item.item)", role: .destructive) {}
Button(action: {}) {
Text("""
delete with item \(item.item)
CANNOT undo this action!!!
""")
}
case .test3:
Button(action: {}) {
VStack {
Text("play with item \(item.item)")
Text("Have a good time!")
}
}
}
Button("Cancel", role: .cancel) {
confirmationItem = nil
}
}
func confirmationDialogMassageView(item: ConfirmationItem) -> some View {
switch item.id {
case .test1:
return Text("Confirm to do with item \(item.item)")
case .test2:
return Text("Confirm to delete item \(item.item)")
case .test3:
return Text("Confirm to play with item \(item.item)")
}
}
}
struct itemView0: View {
@State private var confirmationShown = false
let message: Int
let onDelete: (Int) -> Void
var body: some View {
Text("\(message)")
.swipeActions {
Button(
role: .none,
action: { confirmationShown = true }
) {
Image(systemName: "trash")
}
.tint(Color.red)
}
.confirmationDialog(
"Are you sure?",
isPresented: $confirmationShown,
titleVisibility: .visible,
presenting: message
) { message in
Button("Yes, delete: \(message)") {
onDelete(message)
}.keyboardShortcut(.defaultAction)
Button("No", role: .cancel) {}
} message: { message in
Text("\(message)")
}
}
}
英文:
Yes, we can use "presenting data: T?" to identify the kinds of ConfirmationDialog, just like Binding<Item?> of sheet. I think apple design "isPresented: Binding<Bool>" just to simplify usage without presenting. OR it's not necessary.
here is an example (also see the whole code about ConfirmationDialog):
enum ConfirmationID {
case test1
case test2
case test3
var id: ConfirmationID { self }
}
struct ConfirmationItem: Identifiable {
var id: ConfirmationID
var item: String
}
struct ConfirmationDialog0: View {
@State private var messages: [Int] = (0..<5).map { $0 }
@State private var isPresented: Bool = false
@State private var confirmationItem: ConfirmationItem?
var body: some View {
NavigationView {
GeometryReader { proxy in
ScrollView {
HStack {
Button("test 1") {
confirmationItem = ConfirmationItem(id: .test1, item: "test 1")
isPresented = true
}
Button("test 2") {
confirmationItem = ConfirmationItem(id: .test2, item: "test 2")
isPresented = true
}
Button("test 3") {
confirmationItem = ConfirmationItem(id: .test3, item: "test 3")
isPresented = true
}
}
List {
ForEach(messages, id: \.self) { message in
itemView0(message: message) { _ in
withAnimation {
messages = messages.filter { $0 != message }
}
}
}
}
.frame(height: proxy.size.height)
}
}
.navigationTitle("WRONG if .destructive!")
.confirmationDialog("CONFIRM", isPresented: $isPresented, titleVisibility: .visible, presenting: confirmationItem, actions: confirmationDialogActionsView, message: confirmationDialogMassageView)
}
}
@ViewBuilder
func confirmationDialogActionsView(item: ConfirmationItem) -> some View {
// Group {
switch item.id {
case .test1:
Button(action: {}) {
Text("do with item \(item.item): ") + Text(Image(systemName: "star")) + Text(" World!")
} // NOTE: Text(Image(systemName: "star")) does not work
case .test2:
Button("delete with item \(item.item)", role: .destructive) {}
Button(action: {}) {
Text("""
delete with item \(item.item)
CANNOT undo this action!!!
""")
} // NOTE: multiple lines text does not work. FYI: https://developer.apple.com/documentation/swiftui/view/confirmationdialog(_:ispresented:titlevisibility:presenting:actions:)-51pyu
case .test3:
Button(action: {}) {
VStack {
Text("play with item \(item.item)")
Text("Have a good time!") // NOTE: multiple texts do not work either.
}
}
}
Button("Cancel", role: .cancel) {
confirmationItem = nil
}
// }
}
func confirmationDialogMassageView(item: ConfirmationItem) -> some View {
switch item.id {
case .test1:
return Text("Confirm to do with item \(item.item)")
case .test2:
return Text("Confirm to delete item \(item.item)")
case .test3:
return Text("Confirm to play with item \(item.item)")
}
}
}
struct itemView0: View {
@State private var confirmationShown = false
let message: Int
let onDelete: (Int) -> Void
var body: some View {
Text("\(message)")
.swipeActions {
Button(
role: .none,//.destructive,
action: { confirmationShown = true }
) {
Image(systemName: "trash")
}
.tint(Color.red)
}
.confirmationDialog(
"Are you sure?",
isPresented: $confirmationShown,
titleVisibility: .visible,
presenting: message
) { message in
Button("Yes, delete: \(message)") {
onDelete(message)
}.keyboardShortcut(.defaultAction)
Button("No", role: .cancel) {}
} message: { message in
Text("\(message)")
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论