Guideline 4.2
Guideline 4.2 - Design: WebView-Only App With No Native Functionality
Our Take
Apple rejected your app under Guideline 4.2 because it is essentially a wrapper around a website with no meaningful native iOS functionality. The app’s primary content is displayed through WKWebView or embedded web pages, and it does not leverage native iOS capabilities like push notifications, offline storage, camera, Siri, widgets, or other platform features. Apple considers such apps better suited as websites or Safari bookmarks rather than standalone App Store listings.
Resolution Guide
**Rewrite core screens in native SwiftUI or UIKit** — At minimum, convert the primary user-facing screens to native code. The home screen, navigation, lists, and detail views should all be native:
```swift
// Instead of loading a URL in WKWebView, build native views
List(articles) { article in
NavigationLink(destination: ArticleDetailView(article: article)) {
ArticleRowView(article: article)
}
}
```
**Add push notifications** — Register for remote notifications and send timely, relevant alerts. This is one of the clearest signals that an app is native:
```swift
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound])
```
**Implement offline functionality** — Cache content locally so the app is useful without an internet connection:
- Cache images with URLCache or a library like Kingfisher
- Show cached content with a “last updated” indicator when offline
**Add native iOS features** that a website cannot provide:
- Camera/photo integration: Let users capture or select images natively
- Haptic feedback: Add tactile responses to interactions
- Shortcuts/Siri: Enable voice-driven actions
- Share extension: Let users share content from other apps into yours
**Use native navigation** — Replace web-based navigation with UINavigationController or NavigationStack. Users should feel iOS-native transitions, swipe-back gestures, and standard navigation patterns.
**If some web content is necessary**, use it selectively — It’s acceptable to use WKWebView for specific content like terms of service, help articles, or rich HTML emails. The key is that the majority of the app must be native.
**Test the “airplane mode test”** — Put your phone in airplane mode and open your app. If it’s completely blank or unusable, you haven’t added enough native functionality.
Example Rejection Email
Consider Appealing
Appeals are very unlikely to succeed if your app truly is a web view wrapper. Apple’s policy is firm on this. If your app uses web views for specific content but has substantial native features the reviewer missed, reply with a detailed feature list and screenshots of the native components. Otherwise, invest the time in rebuilding core screens natively.
Before & After
// Entire app: a single WKWebView
struct ContentView: View {
var body: some View {
WebView(url: URL(string: "https://mysite.com")!)
}
}
struct WebView: UIViewRepresentable {
let url: URL
func makeUIView(context: Context) -> WKWebView {
let webView = WKWebView()
webView.load(URLRequest(url: url))
return webView
}
func updateUIView(_ uiView: WKWebView, context: Context) {}
}
// Native app with tabs, offline, and push notifications
@main
struct MyApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
var body: some Scene {
WindowGroup {
TabView {
HomeView() // Native SwiftUI list + search
.tabItem { Label("Home", systemImage: "house") }
FavoritesView() // Locally persisted favorites
.tabItem { Label("Saved", systemImage: "bookmark") }
NotificationsView() // Push notification history
.tabItem { Label("Alerts", systemImage: "bell") }
SettingsView() // Native preferences
.tabItem { Label("Settings", systemImage: "gear") }
}
}
}
}
// AppDelegate handles push notification registration
// SwiftData models for offline content caching
// WidgetBundle for Home Screen widget
What changed: The single WKWebView was replaced with a fully native TabView-based architecture. Each tab renders native SwiftUI views. Push notifications, offline caching via SwiftData, and a Home Screen widget demonstrate native platform integration that a website cannot replicate.
// Web-based content loading — no offline, no native features
func loadContent() {
webView.load(URLRequest(url: URL(string: "https://api.mysite.com/feed")!))
}
// If offline: blank white screen
// Native content loading with offline cache
@Observable
class FeedViewModel {
var articles: [Article] = []
func loadContent() async {
// Try network first
if let remote = try? await APIClient.fetchArticles() {
articles = remote
try? SwiftDataStore.cache(remote) // persist for offline
} else {
// Offline fallback — load cached content
articles = SwiftDataStore.loadCached()
}
}
}
// Native list rendering
struct FeedView: View {
@State var viewModel = FeedViewModel()
var body: some View {
List(viewModel.articles) { article in
ArticleRow(article: article)
}
.refreshable { await viewModel.loadContent() }
.task { await viewModel.loadContent() }
}
}
What changed: Content is fetched via a native API client and rendered in a SwiftUI List instead of a web view. Articles are cached locally with SwiftData so the app works offline. Pull-to-refresh provides a native interaction pattern that web views cannot match.
Community Solutions · 0
Sign in to share your solution.
More Guideline 4 (Design) rejections
- Guideline 4.0 - Design: App Does Not Include iOS Features
- Guideline 4.0 - Design: App Looks Like a Website
- Guideline 4.0 - Design: Apple Pay Button Not Following Guidelines
- Guideline 4.0 - Design: Blurry Icons or Low-Resolution Assets
- Guideline 4.0 - Design: Broken Layout on iPad
- Guideline 4.0 - Design: Content Clipped by Notch or Safe Area