Alert in SwiftUI
There are several ways to present an alert in SwiftUI. Let’s go through them one by one.
1. Alert with title
SwiftUI will present an alert when a given condition is true
, using a text view for the title.
The method definition is below:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
nonisolated
func alert<A>(
_ title: Text,
isPresented: Binding<Bool>,
@ViewBuilder actions: () -> A
) -> some View where A : View
nonisolated
func alert<A>(
_ titleKey: LocalizedStringKey,
isPresented: Binding<Bool>,
@ViewBuilder actions: () -> A
) -> some View where A : View
nonisolated
func alert<S, A>(
_ title: S,
isPresented: Binding<Bool>,
@ViewBuilder actions: () -> A
) -> some View where S : StringProtocol, A : View
This is a simplest form for an alert. Let’s see an example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
struct LoginView: View {
@EnvironmentObject var authStore: AuthStore
@State private var username = ""
@State private var password = ""
@State private var showingErrorAlert = false
var body: some View {
VStack {
// ...
Button("Log in", action: login)
}
.alert("Login failed.", isPresented: $showingErrorAlert) {
Button("OK", role: .cancel) { }
}
}
private func login() {
Task {
do {
try await authStore.login(username: username, password: password)
} catch {
showingErrorAlert = true
}
}
}
}
In the above example, SwiftUI will present an error alert when showingErrorAlert
is true
.
2. Alert with title and message
You can also present an alert with a message when a given condition is true
.
The method definition is as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
nonisolated
func alert<A, M>(
_ title: Text,
isPresented: Binding<Bool>,
@ViewBuilder actions: () -> A,
@ViewBuilder message: () -> M
) -> some View where A : View, M : View
nonisolated
func alert<A, M>(
_ titleKey: LocalizedStringKey,
isPresented: Binding<Bool>,
@ViewBuilder actions: () -> A,
@ViewBuilder message: () -> M
) -> some View where A : View, M : View
nonisolated
func alert<S, A, M>(
_ title: S,
isPresented: Binding<Bool>,
@ViewBuilder actions: () -> A,
@ViewBuilder message: () -> M
) -> some View where S : StringProtocol, A : View, M : View
A simple code example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
struct LoginView: View {
@EnvironmentObject var authStore: AuthStore
@State private var username = ""
@State private var password = ""
@State private var errorMessage = ""
@State private var showingErrorAlert = false
var body: some View {
VStack {
// ...
Button("Log in", action: login)
}
.alert("Error", isPresented: $showingErrorAlert) {
Button("OK", role: .cancel) {}
} message: {
Text(errorMessage)
}
}
private func login() {
Task {
do {
try await authStore.login(username: username, password: password)
} catch {
errorMessage = error.localizedDescription
showingErrorAlert = true
}
}
}
}
SwiftUI will present an alert with message when showingErrorAlert
is true
.
3. Alert using data
We are able to present an alert using the given data to produce the alert’s actions.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
nonisolated
func alert<A, T>(
_ title: Text,
isPresented: Binding<Bool>,
presenting data: T?,
@ViewBuilder actions: (T) -> A
) -> some View where A : View
nonisolated
func alert<A, T>(
_ titleKey: LocalizedStringKey,
isPresented: Binding<Bool>,
presenting data: T?,
@ViewBuilder actions: (T) -> A
) -> some View where A : View
nonisolated
func alert<S, A, T>(
_ title: S,
isPresented: Binding<Bool>,
presenting data: T?,
@ViewBuilder actions: (T) -> A
) -> some View where S : StringProtocol, A : View
For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
struct LoginView: View {
@EnvironmentObject var authStore: AuthStore
@State private var username: String = ""
@State private var password: String = ""
@State private var error: Error? = nil
@State private var showingErrorAlert = false
var body: some View {
VStack {
// ...
Button("Log in", action: login)
}
.alert("Login failed.", isPresented: $showingErrorAlert, presenting: error) { error in
if error.needRetry {
Button("Retry") { // ... }
}
Button("OK", role: .cancel) {}
}
}
private func login() {
Task {
do {
try await authStore.login(username: username, password: password)
} catch {
self.error = error
showingErrorAlert = true
}
}
}
}
SwiftUI will present the alert when showingErrorAlert
is true
and call actions
ViewBuilder when error
is not nil
. After the alert is dismissed, the showingErrorAlert
will be set to false
, however, error
will remain unchanged.
4. Alert with title and message using data
We are able to present an alert with title and message using the given data to produce the alert’s actions and message as well.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
nonisolated
func alert<A, M, T>(
_ title: Text,
isPresented: Binding<Bool>,
presenting data: T?,
@ViewBuilder actions: (T) -> A,
@ViewBuilder message: (T) -> M
) -> some View where A : View, M : View
nonisolated
func alert<A, M, T>(
_ titleKey: LocalizedStringKey,
isPresented: Binding<Bool>,
presenting data: T?,
@ViewBuilder actions: (T) -> A,
@ViewBuilder message: (T) -> M
) -> some View where A : View, M : View
nonisolated
func alert<S, A, M, T>(
_ title: S,
isPresented: Binding<Bool>,
presenting data: T?,
@ViewBuilder actions: (T) -> A,
@ViewBuilder message: (T) -> M
) -> some View where S : StringProtocol, A : View, M : View
The code example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
struct LoginView: View {
@EnvironmentObject var authStore: AuthStore
@State private var username: String = ""
@State private var password: String = ""
@State private var error: Error? = nil
@State private var showingErrorAlert = false
var body: some View {
VStack {
// ...
Button("Log in", action: login)
}
.alert("Error", isPresented: $showingErrorAlert, presenting: error) { error in
if error.needRetry {
Button("Retry") { // ... }
}
Button("OK", role: .cancel) {}
} message: { error in
Text(error.localizedDescription)
}
}
private func login() {
Task {
do {
try await authStore.login(username: username, password: password)
} catch {
self.error = error
showingErrorAlert = true
}
}
}
}