Guideline 4.0

Guideline 4.0 - Design: Excessive or Inappropriate Alerts

Low RiskEasyTypical Fix: 1-3 hours0 Reports
Also known as:Multiple alerts appear back-to-back on app launchSystem alert used for a review or rating prompt instead of SKStoreReviewControllerAlerts used to display tips, tutorials, or onboarding informationSuccess confirmations shown as alerts instead of inline feedbackAlert chains that force the user to dismiss several dialogs before using the app

Our Take

Apple rejected your app because it displays too many alerts, uses system alerts (UIAlertController) for non-critical information, or presents alerts at inappropriate times such as immediately on launch. System alerts are interruptive by design and should be reserved for critical decisions or errors. Using them for tips, announcements, ratings prompts, onboarding information, or non-blocking messages degrades the user experience.

Resolution Guide

01

**Audit all alert usage** — Search your codebase for `UIAlertController`, `.alert(`, and `Alert(` to find every alert in your app. Categorize each as critical (requires user decision) or non-critical (informational).


02

**Replace non-critical alerts with inline UI** — For success confirmations, use a toast or banner that auto-dismisses. For tips, use an inline card or tooltip. For feature announcements, use a non-modal sheet or "what's new" screen:

```swift

// Instead of an alert for success:

withAnimation { showSuccessBanner = true }

DispatchQueue.main.asyncAfter(deadline: .now() + 2) {

withAnimation { showSuccessBanner = false }

}

```

03

**Use SKStoreReviewController for ratings** — Never build a custom rating alert. Use the system API which Apple controls and rate-limits automatically:

```swift

import StoreKit

if let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene {

SKStoreReviewController.requestReview(in: scene)

}

```

04

**Stagger permission requests** — Do not ask for notifications, location, camera, etc. all at once on launch. Request each permission only when the user reaches a feature that needs it, and explain why before showing the system dialog.


05

**Remove alert chains** — Never present alerts sequentially. If you need multiple pieces of information from the user, use a multi-step form or onboarding flow instead.


06

**Reserve alerts for critical decisions** — Alerts should be used for: destructive actions ("Delete this item?"), authentication failures, required updates, or irrecoverable errors. Almost nothing else warrants a system alert.


07

**Test the first launch experience** — Reset your app and walk through the first launch. Count how many alerts appear before the user can interact with the main content. The ideal number is zero.


Example Rejection Email

From:Apple App Review Team
Subject:Guideline 4.0 - Design: Excessive or Inappropriate Alert
Your app displays excessive system alerts that disrupt the user experience. Specifically, upon launch your app presents a system alert requesting a review, followed by an alert about new features, and then an alert asking to enable notifications. Additionally, the app uses system alerts to display non-critical information such as tips and success confirmations. System alerts should only be used for critical information that requires an immediate decision. Next Steps: Please reduce the number of alerts and use non-interruptive alternatives for non-critical messages.

Consider Appealing

Do not appeal. Reduce the number of alerts and replace non-critical ones with inline UI. This rejection is straightforward to fix and Apple is consistent about enforcing it.

Generate Appeal

Before & After

Before — Rejected

// Excessive: alert for non-critical success message

func saveCompleted() {

let alert = UIAlertController(

title: "Success!",

message: "Your changes have been saved.",

preferredStyle: .alert

)

alert.addAction(UIAlertAction(title: "OK", style: .default))

present(alert, animated: true)

}

After — Approved

// Non-interruptive: inline toast banner for success

@State private var showSavedBanner = false


func saveCompleted() {

withAnimation(.spring()) { showSavedBanner = true }

DispatchQueue.main.asyncAfter(deadline: .now() + 2) {

withAnimation { showSavedBanner = false }

}

}


// In the view body:

.overlay(alignment: .top) {

if showSavedBanner {

Text("Changes saved")

.padding()

.background(.thinMaterial, in: Capsule())

.transition(.move(edge: .top).combined(with: .opacity))

}

}

What changed: Replace success confirmation alerts with a non-interruptive toast banner that auto-dismisses. The user sees the confirmation without having to tap 'OK' to continue using the app.

Before — Rejected

// Custom rating alert — violates guidelines

let alert = UIAlertController(

title: "Enjoying the app?",

message: "Please rate us on the App Store!",

preferredStyle: .alert

)

alert.addAction(UIAlertAction(title: "Rate Now", style: .default) { _ in

// open App Store

})

alert.addAction(UIAlertAction(title: "Later", style: .cancel))

present(alert, animated: true)

After — Approved

// System rating prompt — Apple-controlled, rate-limited

import StoreKit


func requestReviewIfAppropriate() {

guard let scene = UIApplication.shared.connectedScenes

.first(where: { $0.activationState == .foregroundActive })

as? UIWindowScene else { return }

SKStoreReviewController.requestReview(in: scene)

}

What changed: SKStoreReviewController presents Apple's own rating dialog, which is rate-limited to 3 times per year per app. Apple controls the presentation and timing, ensuring it doesn't annoy users.

Community Solutions · 0

Sign in to share your solution.

More Guideline 4 (Design) rejections

View all Guideline 4 rejections