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:

  1. Open your project in Xcode.
  2. Select your App Target and navigate to Signing & Capabilities.
  3. 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.