Configure iOS 16 Focus Filters to Hide Views
Focus filters in iOS 16 allow apps to dynamically adjust their interfaces and hide distracting views based on the user's active Focus mode, such as Work or Personal. By integrating the App Intents framework, developers can define custom filter settings that the operating system triggers when a Focus status changes. This article explains how to define a Focus filter intent, observe configuration updates, and update your SwiftUI or UIKit hierarchy to conditionally hide views.
1. Adopt the SetFocusFilterIntent Protocol
To create a Focus filter, your project must import the
AppIntents framework and define a structure conforming to
SetFocusFilterIntent. This protocol informs the system that
your app provides actions configurable through the Settings app under
Focus customization.
import AppIntents
struct AppModeFocusFilter: SetFocusFilterIntent {
static var title: LocalizedStringResource = "Filter App Views"
static var description: LocalizedStringResource? = "Hide specific tabs and views based on the active Focus."
// Define the configurable parameter
@Parameter(title: "Hide Social Feeds", default: false)
var hideSocialViews: Bool
var displayRepresentation: DisplayRepresentation {
DisplayRepresentation(title: "Hide Social Feeds")
}
func perform() async throws -> some IntentResult {
// Broadcast the new state to your application state manager
await AppStateManager.shared.updateViewVisibility(hideSocialViews: hideSocialViews)
return .result()
}
}2. Manage the Focus Filter State
The execution of the perform() method happens in the
background or during active runtime whenever the user toggles a Focus
mode. Store this state in an observable class or a centralized
dependency to bridge the intent with your user interface.
import SwiftUI
@MainActor
final class AppStateManager: ObservableObject {
static let shared = AppStateManager()
@Published var shouldHideViews: Bool = false
func updateViewVisibility(hideSocialViews: Bool) {
self.shouldHideViews = hideSocialViews
}
}3. Handle System Updates in the App Lifecycle
If the app is not running when the user changes the Focus mode, iOS updates the intent values. You should check the current intent state when the app launches or returns to the foreground.
If your intent conforms to SetFocusFilterIntent, you can
also inspect the current filter context via the app delegate or scene
delegate using AppContext:
// In your App struct or SceneDelegate
@main
struct FocusAwareApp: App {
@StateObject private var stateManager = AppStateManager.shared
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(stateManager)
}
}
}4. Conditionally Hide Views in the UI
Once the state is linked, modify your view hierarchy to remove or hide views, tabs, or navigation links based on the active filter.
In SwiftUI:
struct ContentView: View {
@EnvironmentObject var stateManager: AppStateManager
var body: some View {
TabView {
WorkDashboardView()
.tabItem {
Label("Work", systemImage: "briefcase")
}
// Hide the view completely when the Focus filter is active
if !stateManager.shouldHideViews {
SocialFeedView()
.tabItem {
Label("Feed", systemImage: "bubble.left.and.bubble.right")
}
}
}
}
}In UIKit:
For UIKit-based apps, observe updates from your state manager inside
your UITabBarController or navigation controllers, then
update the visible view controllers accordingly:
class MainTabBarController: UITabBarController {
func applyFocusFilter(hideSocialViews: Bool) {
if hideSocialViews {
// Remove social tabs
self.viewControllers = [workNavigationController]
} else {
// Restore all tabs
self.viewControllers = [workNavigationController, socialNavigationController]
}
}
}5. Add Focus Filter Capabilities to Xcode
To ensure iOS recognizes the filter:
- Open your project in Xcode.
- Select your App Target and navigate to Signing & Capabilities.
- Click + Capability and add Focus Filters.
When configured, users can navigate to Settings > Focus, select any Focus mode, scroll to Focus Filters, choose Add Filter, and select your app to toggle the custom interface options.