Reputation: 357
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
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
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
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
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
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