Alert và Confirmation trong SwiftUI
1. Alert cơ bản
struct ContentView: View {
@State private var showAlert = false
var body: some View {
Button("Show Alert") {
showAlert = true
}
.alert("Title", isPresented: $showAlert) {
Button("OK") { }
} message: {
Text("This is the alert message")
}
}
}2. Alert với Actions
.alert("Delete Item?", isPresented: $showDeleteAlert) {
Button("Delete", role: .destructive) {
deleteItem()
}
Button("Cancel", role: .cancel) { }
} message: {
Text("This action cannot be undone.")
}3. Alert với Data
struct ContentView: View {
@State private var selectedItem: Item?
var body: some View {
List(items) { item in
Button(item.name) {
selectedItem = item
}
}
.alert(item: $selectedItem) { item in
Alert(
title: Text("Delete \(item.name)?"),
primaryButton: .destructive(Text("Delete")) {
delete(item)
},
secondaryButton: .cancel()
)
}
}
}4. Alert với TextField
struct RenameView: View {
@State private var showRename = false
@State private var newName = ""
var body: some View {
Button("Rename") {
showRename = true
}
.alert("Rename Item", isPresented: $showRename) {
TextField("New name", text: $newName)
Button("Rename") {
rename(to: newName)
}
Button("Cancel", role: .cancel) { }
} message: {
Text("Enter a new name for this item")
}
}
}5. Confirmation Dialog
struct ContentView: View {
@State private var showOptions = false
var body: some View {
Button("Share") {
showOptions = true
}
.confirmationDialog("Share", isPresented: $showOptions) {
Button("Copy Link") { }
Button("Share via Message") { }
Button("Share via Email") { }
Button("Cancel", role: .cancel) { }
} message: {
Text("Choose how to share")
}
}
}6. Action Sheet Style
.confirmationDialog(
"Options",
isPresented: $showOptions,
titleVisibility: .visible
) {
Button("Edit") { }
Button("Duplicate") { }
Button("Delete", role: .destructive) { }
}7. Error Handling
struct ContentView: View {
@State private var error: AppError?
enum AppError: LocalizedError, Identifiable {
case network
case unauthorized
case unknown
var id: Self { self }
var errorDescription: String? {
switch self {
case .network: return "Network Error"
case .unauthorized: return "Unauthorized"
case .unknown: return "Unknown Error"
}
}
var recoverySuggestion: String? {
switch self {
case .network: return "Check your internet connection"
case .unauthorized: return "Please login again"
case .unknown: return "Please try again later"
}
}
}
var body: some View {
Button("Load Data") {
loadData()
}
.alert(item: $error) { error in
Alert(
title: Text(error.errorDescription ?? "Error"),
message: Text(error.recoverySuggestion ?? ""),
dismissButton: .default(Text("OK"))
)
}
}
func loadData() {
// Simulate error
error = .network
}
}8. Toast-style Notification
struct ToastView: View {
let message: String
var body: some View {
Text(message)
.padding()
.background(.black.opacity(0.7))
.foregroundColor(.white)
.cornerRadius(8)
}
}
struct ContentView: View {
@State private var showToast = false
var body: some View {
ZStack {
Button("Show Toast") {
showToast = true
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
showToast = false
}
}
if showToast {
VStack {
Spacer()
ToastView(message: "Item saved!")
.transition(.move(edge: .bottom).combined(with: .opacity))
.padding(.bottom, 50)
}
.animation(.easeInOut, value: showToast)
}
}
}
}📝 Tóm tắt
| Component | Mục đích |
|---|---|
.alert | Dialog notification |
.confirmationDialog | Action sheet |
Button(role: .destructive) | Red destructive action |
Button(role: .cancel) | Cancel action |
Last updated on