iOS development
Android Toast equivalent
Swift programming
mobile app development
user interface design

Displaying a message in iOS which has the same functionality as Toast in Android

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

iOS has no built-in Toast equivalent. The closest native approach is a UIAlertController with a timer that dismisses it automatically, but this is modal and blocks interaction. The idiomatic iOS alternatives are: a temporary UILabel overlay that fades out (custom Toast view), a third-party library like SwiftMessages or JDStatusBarNotification, or in SwiftUI, a custom .overlay() modifier with animation. For the most common case, a custom Toast view class that adds a label to the window and animates it away is the simplest solution.

Method 1: Custom Toast View (UIKit)

swift
1import UIKit
2
3extension UIViewController {
4    func showToast(message: String, duration: Double = 2.0) {
5        let toastLabel = UILabel()
6        toastLabel.backgroundColor = UIColor.black.withAlphaComponent(0.7)
7        toastLabel.textColor = .white
8        toastLabel.textAlignment = .center
9        toastLabel.font = UIFont.systemFont(ofSize: 14)
10        toastLabel.text = message
11        toastLabel.alpha = 0
12        toastLabel.layer.cornerRadius = 10
13        toastLabel.clipsToBounds = true
14        toastLabel.numberOfLines = 0
15
16        let maxWidth = view.frame.width - 40
17        let textSize = toastLabel.sizeThatFits(CGSize(width: maxWidth, height: .greatestFiniteMagnitude))
18        let width = min(textSize.width + 40, maxWidth)
19        let height = textSize.height + 20
20
21        toastLabel.frame = CGRect(
22            x: (view.frame.width - width) / 2,
23            y: view.frame.height - 120,
24            width: width,
25            height: height
26        )
27
28        view.addSubview(toastLabel)
29
30        UIView.animate(withDuration: 0.3, animations: {
31            toastLabel.alpha = 1
32        }) { _ in
33            UIView.animate(withDuration: 0.3, delay: duration, options: [], animations: {
34                toastLabel.alpha = 0
35            }) { _ in
36                toastLabel.removeFromSuperview()
37            }
38        }
39    }
40}
41
42// Usage
43showToast(message: "Item saved successfully")
44showToast(message: "Network error", duration: 3.0)

Method 2: SwiftUI Toast

swift
1import SwiftUI
2
3struct ToastModifier: ViewModifier {
4    @Binding var isShowing: Bool
5    let message: String
6    let duration: Double
7
8    func body(content: Content) -> some View {
9        ZStack(alignment: .bottom) {
10            content
11
12            if isShowing {
13                Text(message)
14                    .padding(.horizontal, 16)
15                    .padding(.vertical, 10)
16                    .background(Color.black.opacity(0.7))
17                    .foregroundColor(.white)
18                    .cornerRadius(10)
19                    .padding(.bottom, 50)
20                    .transition(.opacity)
21                    .onAppear {
22                        DispatchQueue.main.asyncAfter(deadline: .now() + duration) {
23                            withAnimation {
24                                isShowing = false
25                            }
26                        }
27                    }
28            }
29        }
30        .animation(.easeInOut(duration: 0.3), value: isShowing)
31    }
32}
33
34extension View {
35    func toast(isShowing: Binding<Bool>, message: String, duration: Double = 2.0) -> some View {
36        modifier(ToastModifier(isShowing: isShowing, message: message, duration: duration))
37    }
38}
39
40// Usage
41struct ContentView: View {
42    @State private var showToast = false
43
44    var body: some View {
45        VStack {
46            Button("Show Toast") {
47                showToast = true
48            }
49        }
50        .toast(isShowing: $showToast, message: "Item saved!")
51    }
52}

Method 3: UIAlertController with Auto-Dismiss

swift
1func showAutoAlert(message: String, seconds: Double = 1.5) {
2    let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert)
3    present(alert, animated: true)
4
5    DispatchQueue.main.asyncAfter(deadline: .now() + seconds) {
6        alert.dismiss(animated: true)
7    }
8}
9
10// Usage
11showAutoAlert(message: "Copied to clipboard")

This is the quickest approach but is modal — it dims the background and blocks user interaction until dismissed.

Method 4: Status Bar Notification

swift
1// Using a status bar-style notification (top of screen)
2extension UIViewController {
3    func showStatusBarToast(message: String, duration: Double = 2.0) {
4        guard let window = view.window else { return }
5
6        let banner = UIView()
7        banner.backgroundColor = UIColor.systemGreen
8        banner.frame = CGRect(x: 0, y: -60, width: window.frame.width, height: 60)
9
10        let label = UILabel()
11        label.text = message
12        label.textColor = .white
13        label.textAlignment = .center
14        label.font = UIFont.boldSystemFont(ofSize: 14)
15        label.frame = CGRect(x: 16, y: 20, width: banner.frame.width - 32, height: 30)
16
17        banner.addSubview(label)
18        window.addSubview(banner)
19
20        UIView.animate(withDuration: 0.3, animations: {
21            banner.frame.origin.y = 0
22        }) { _ in
23            UIView.animate(withDuration: 0.3, delay: duration, animations: {
24                banner.frame.origin.y = -60
25            }) { _ in
26                banner.removeFromSuperview()
27            }
28        }
29    }
30}

Android Toast for Reference

kotlin
// Android — one line
Toast.makeText(context, "Item saved", Toast.LENGTH_SHORT).show()

Common Pitfalls

  • Using UIAlertController as a Toast replacement: UIAlertController is modal — it blocks user interaction and dims the background, which is the opposite of Toast behavior. Use a non-modal overlay view instead.
  • Adding the Toast to the view controller's view instead of the window: If the view controller transitions or is dismissed while the Toast is visible, the Toast disappears too. Adding to the UIWindow ensures the Toast outlives navigation transitions.
  • Not removing the Toast label from the superview after animation: Forgetting toastLabel.removeFromSuperview() in the completion handler causes invisible views to accumulate in the view hierarchy, leaking memory over time.
  • Hardcoding Toast position without accounting for safe areas: On devices with notches (iPhone X+), a Toast at y = view.frame.height - 100 may overlap with the home indicator. Use view.safeAreaInsets.bottom to position correctly.
  • Showing multiple Toasts simultaneously without a queue: If the user triggers multiple Toasts quickly, they stack on top of each other. Implement a queue that waits for the current Toast to dismiss before showing the next one, or cancel the current Toast and show the new one.

Summary

  • iOS has no built-in Toast — use a custom UILabel overlay with fade animation for the closest equivalent
  • In SwiftUI, use a custom ViewModifier with @Binding and onAppear auto-dismiss
  • Avoid UIAlertController for Toast-like behavior — it blocks user interaction
  • Add Toasts to the UIWindow to survive view controller transitions
  • Account for safe areas and queue multiple Toasts to avoid stacking

Course illustration
Course illustration

All Rights Reserved.