You must use the AppTrackingTransparency framework if your app collects data about end users and shares it with other companies for purposes of tracking across apps and web sites (https://developer.apple.com/documentation/apptrackingtransparency).
In this post we’ll see how implement what iOS require for the tracking and i’ll use this example also to explain other concepts.
Let’s start from the end, we want this:
Swift with Storyboard
Create a iOS project using a storyboard:
After that, we add a WebView to the storyboard and apply the constrains to have the webview in full-screen. We must add a string value for the “Privacy – Tracking Description usage” in the info tab. This message have to explain because the user is tracked.
First add an outlet for the webview:
import UIKit import WebKit class ViewController: UIViewController { @IBOutlet weak var webView: WKWebView! override func viewDidLoad() { super.viewDidLoad() } }
We have to add the import for the Tracking API in the SceneDelegate.swift:
import AdSupport import AppTrackingTransparency
Now add the code to show the dialog.
struct RequestManager { static func getIDFA() -> String { return ASIdentifierManager.shared().advertisingIdentifier.uuidString } static func checkTrackingStatus(completionHandler: @escaping (ATTrackingManager.AuthorizationStatus) -> Void) { ATTrackingManager.requestTrackingAuthorization { status in DispatchQueue.main.async { completionHandler(status) } } } }
We create a struct RequestManager, it has two static function, the getIDFA return the Identifier For Advertisers, an UUID used to track the device.
The function checkTrackingStatus is a static function (because is defined in a struct, see https://holyswift.app/the-difference-between-class-func-and-static-func-in-swift-and-why-polymorphism-matters for long explaination) that show (in async way) the dialog to get the permission from the user.
See what’s change in the SceneDelegate:
func sceneDidBecomeActive(_ scene: UIScene) { // Called when the scene has moved from an inactive state to an active state. // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. attRequest() } func attRequest() { RequestManager.checkTrackingStatus { status in switch status { case .authorized: print("Authorized") case .denied: print("Denied") case .notDetermined: print("NotDetermined") self.attRequest() case .restricted: print("Restricted") @unknown default: break } } }
In the sceneDidBecomeActive call the our function attRequest; this function call checkTrackingStatus with a closure, this function gets the status, if the status is notDetermined, the function call itself to re-ask the authorization. Note that we get also the IDFA but in our case we don’t use it.
The code https://github.com/niqt/ShowWebsite
In SwiftUI
How have this using SwiftUI? More simple, add always the string in the plist.info to request the permission and in the code write:
import SwiftUI import AdSupport import AppTrackingTransparency struct ContentView: View { var body: some View { VStack { Text("Got the permission!") }.onReceive(NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification)) { _ in ATTrackingManager.requestTrackingAuthorization(completionHandler: { status in switch status { case .authorized: print("A") case .denied: print("D") case .notDetermined: print("E") case .restricted: print(" restricted") @unknown default: break } }) } } }
In this case the view require the tracking authorization calling the ATTrackingManager in the onReceive of the VStack (just for example). That’s all.
Note: English is not my native language, so I’m sorry for some errors. I appreciate it if you correct me.