IDFA iOS14 returns 拒绝显示身份验证弹出窗口

IDFA iOS14 returns denied without displaying auth popup

我正在研究如何在 iOS 14 上获取 IDFA。我正在使用 iPhone 8 Plus。

我已经添加了

<key>NSUserTrackingUsageDescription</key>
<string>App would like to access IDFA for tracking purpose</string>

.plist 文件中。

然后添加

let type = ATTrackingManager.trackingAuthorizationStatus;

其中returns.denied,有

func requestPermission() {
        ATTrackingManager.requestTrackingAuthorization { status in
            switch status {
            case .authorized:
                // Tracking authorization dialog was shown
                // and we are authorized
                print("Authorized")
            
                // Now that we are authorized we can get the IDFA
            print(ASIdentifierManager.shared().advertisingIdentifier)
            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")
            }
        }
    }

但是我 .denied 没有任何弹出窗口。

你知道这是怎么回事吗?

在系统的设置应用程序中有一个选项“允许应用程序请求跟踪”,如果关闭,requestTrackingAuthorization 将return .denied立即。

我这边的愚蠢问题,你真的在​​调用函数吗? 请记住,一旦回答,它就不会再出现。 您必须删除并安装应用程序才能再次显示它

因为用户拒绝了权限

您可以通过我的代码将用户移动到应用程序的设置页面

UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!, options: [:], completionHandler: nil)

看来你需要使用 iOS 14.4.

我假设你之前设置过一次允许/拒绝。我遇到了同样的问题,即使在我使用 iOS 14.0 尝试卸载应用程序时,请求权限警报也再也不会出现。 但是当我使用 iOS 到 14.4 时,我可以重置设置并通过卸载我的应用程序再次看到询问警报。

如果全局设置允许应用程序请求跟踪关闭,requestTrackingAuthorization将立即return.denied

但对于某些用户,即使在 允许应用程序请求跟踪 开启后,requestTrackingAuthorization returning .denied

这是 OS 问题,已在 14.5.1 版本中修复,因此只需更新您的 OS 即可获取 ATT 对话框。

iOS 和 iPadOS 14.5.1

的发行说明

This update fixes an issue with App Tracking Transparency where some users who previously disabled Allow Apps to Request to Track in Settings may not receive prompts from apps after re-enabling it. This update also provides important security updates and is recommended for all users.

在 iOS 15 中,仅当应用程序状态已经处于活动状态时,才可以使用 ATTrackingManager.requestTrackingAuthorization 请求它,因此应该从 didFinishLaunchingWithOptions 移动到 applicationDidBecomeActive

SwiftUI iOS 15+

要显示 ATTrackingManager.requestTrackingAuthorization 的警报,您必须确保在应用程序处于活动状态时调用它(否则不会显示警报)

为此,我使用 Publisher 进行检查

ContentView()
            .onReceive(NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification)) { _ in
                if ATTrackingManager.trackingAuthorizationStatus == .notDetermined {
                    ATTrackingManager.requestTrackingAuthorization { status in
                        //Whether or not user has opted in initialize GADMobileAds here it will handle the rest
                                                                    
                        GADMobileAds.sharedInstance().start(completionHandler: nil)
                        }
                } else {
                    GADMobileAds.sharedInstance().start(completionHandler: nil)
                    
                }

授权方法ATTrackingManager.requestTrackingAuthorization的调用必须放在主控制器的viewDidAppear(_:)方法中甚至更远(运行之后),即可以绑定到一个按钮

我在隐藏推送通知权限对话框 (completionHandler) 后立即请求跟踪权限。它总是返回被拒绝,奇怪的是增加一秒的延迟为我修复了它。

DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
  // Your dialog
}

您需要将您的代码移动到 AppDelegate,并且 运行 在应用程序激活时将其移动,如 @Serg Smyk 所说。

 func applicationDidBecomeActive(_ application: UIApplication) {
    if #available(iOS 14, *) {
        ATTrackingManager.requestTrackingAuthorization { 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")
            }
        }
    }
}

在 SwiftUI 中:

添加一个属性捕捉ScenePhase,然后:

@Environment(\.scenePhase) var scenePhase

struct ContentView: View {
    @Environment(\.scenePhase) var scenePhase

    var body: some View {
        Text("Hello, world!")
            .padding()
            .onChange(of: scenePhase) { newPhase in
                if newPhase == .active {
                    print("Active")
                    if #available(iOS 14, *) {
                        ATTrackingManager.requestTrackingAuthorization { 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 if newPhase == .inactive {
                    print("Inactive")
                } else if newPhase == .background {
                    print("Background")
                }
            }
    }
}