donchan
donchan

Reputation: 357

iOS 15: How to display ATT dialog when the app starts in SwiftUI

In iOS 14, It could display ATT (App Tracking Transparency) dialog when app starts in SwiftUI as follows.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
    if #available(iOS 14, *) {
        ATTrackingManager.requestTrackingAuthorization(completionHandler: { status in
            // loadAd()
        })
    } else {
        // loadAd()
    }
    return true
}

But, in iOS 15.0, it does not work. Apple document describes as follows.

Calls to the API only prompt when the application state is: UIApplicationStateActive. Calls to the API through an app extension do not prompt. https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/3547037-requesttrackingauthorization

How to display ATT dialog when the app starts in iOS 15 ?

2021/9/28 update I solved it as follows.

struct HomeView: View {
    var body: some View {
        VStack {
            Text("Hello!")
        }.onReceive(NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification)) { _ in
            ATTrackingManager.requestTrackingAuthorization(completionHandler: { status in })
        }
    }
}

Upvotes: 16

Views: 11727

Answers (5)

Siddhesh Bhide
Siddhesh Bhide

Reputation: 424

Instead of calling app tracking transparency permission in didFinishLaunchingWithOptions call in applicationDidBecomeActive it will solve your issue

In AppDelegate

func applicationDidBecomeActive(_ application: UIApplication) {
    requestDataPermission()
}

func requestDataPermission() {
    if #available(iOS 14, *) {
        ATTrackingManager.requestTrackingAuthorization(completionHandler: { status in
            switch status {
            case .authorized:
                // Tracking authorization dialog was shown
                // and we are authorized
                print("Authorized")
            case .denied:
                // Tracking authorization dialog was
                // shown and permission is denied
                print("Denied")
            case .notDetermined:
                // Tracking authorization dialog has not been shown
                print("Not Determined")
            case .restricted:
                print("Restricted")
            @unknown default:
                print("Unknown")
            }
        })
    } else {
        //you got permission to track, iOS 14 is not yet installed
    }
}

in info.plist

<key>NSUserTrackingUsageDescription</key>
<string>Reason_for_data_tracking</string>

Upvotes: 15

Abhishek Suryawanshi
Abhishek Suryawanshi

Reputation: 51

For iOS 15, I faced the same problems and I fixed them by delaying code execution for a second.

DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
        if #available(iOS 14, *) {
            ATTrackingManager.requestTrackingAuthorization(completionHandler: { status in
                DispatchQueue.main.async {
                    self.bannerView.load(GADRequest())
                    self.interstitial.load(request)
                }
            })
        } else {
            // Fallback on earlier versions
            self.bannerView.load(GADRequest())
            self.interstitial.load(request)
        }
    }

Upvotes: 4

Sergei Volkov
Sergei Volkov

Reputation: 1144

A very important addition to all the answers above: the ATT dialogue must be invoked once! If, for example, inside the advertising manager you have repeated calls to the ATT dialog before requesting an advertisement (as it was for previous OS versions), then the dialog WILL NOT be shown! Therefore, the ATT dialogue request must be inserted directly into the view and with a delay of at least 1 second for its unconditional triggering.

Upvotes: 0

Sheikh Wahab Mahmood
Sheikh Wahab Mahmood

Reputation: 428

As @donchan already mentioned use the following code:

struct HomeView: View {
    var body: some View {
        VStack {
            Text("Hello!")
        }.onReceive(NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification)) { _ in
            ATTrackingManager.requestTrackingAuthorization(completionHandler: { status in })
        }
    }
}

Upvotes: 8

uikenan
uikenan

Reputation: 64

If you are writing a SwiftUI app, you can trigger it on your start screen.

struct HomeView: View {
    
    var body: some View {
        VStack {
            Text("Hello!")
        }.onAppear {
            ATTrackingManager.requestTrackingAuthorization(completionHandler: { status in })
        }
    }
}

Do not forget to add the necessary additions to the .plist.

<key>NSUserTrackingUsageDescription</key>
<string>...</string>

Thus, it will run on the simulator or real device.

Upvotes: -1

Related Questions