My app is used to build with Swift 6
and it works perfectly fine. However, since I am using Google AdMob for monetization, I have to implement the App Tracking Transparency (ATT) prompt dialog at the start of the app.
This is my current implementation:
import SwiftUI
import GoogleMobileAds
import AppTrackingTransparency
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Initialize Mobile Ads SDK
MobileAds.shared.start(completionHandler: nil)
// Request ATT authorization after a delay
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
self.requestIDFA()
}
return true
}
func requestIDFA() {
ATTrackingManager.requestTrackingAuthorization { status in
// Handle authorization status
switch status {
case .authorized:
print("ATT: User authorized tracking")
case .denied:
print("ATT: User denied tracking")
case .restricted:
print("ATT: Tracking is restricted")
case .notDetermined:
print("ATT: User has not made a choice")
@unknown default:
print("ATT: Unknown status")
}
}
}
}
@main
struct MyApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
I tested with iOS 16 and 17, and it works as expected. But when I tested on iOS 18 emulator, the prompt appears, click on the Allow
or Not Allow
, and it froze. The user choice is still registered as ATT: User authorized tracking
show in the log (and after exit the app and open again, the log still show the correct user ATT choice).
The problem is relating to thread assertion issue. For example:
Thread 2 Queue : com.apple.root.default-qos (concurrent)
#0 0x00000001023e4214 in _dispatch_assert_queue_fail ()
#12 0x00000001025afb38 in _pthread_wqthread ()
My solution: After trying to debug, I found out that I only need to switch from Swift 6
to Swift 5
. And the application works again.
My Request: My request is that I still want to build the app with Swift 6
(for future proof purposes), how can I do so? Thanks~
My app is used to build with Swift 6
and it works perfectly fine. However, since I am using Google AdMob for monetization, I have to implement the App Tracking Transparency (ATT) prompt dialog at the start of the app.
This is my current implementation:
import SwiftUI
import GoogleMobileAds
import AppTrackingTransparency
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Initialize Mobile Ads SDK
MobileAds.shared.start(completionHandler: nil)
// Request ATT authorization after a delay
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
self.requestIDFA()
}
return true
}
func requestIDFA() {
ATTrackingManager.requestTrackingAuthorization { status in
// Handle authorization status
switch status {
case .authorized:
print("ATT: User authorized tracking")
case .denied:
print("ATT: User denied tracking")
case .restricted:
print("ATT: Tracking is restricted")
case .notDetermined:
print("ATT: User has not made a choice")
@unknown default:
print("ATT: Unknown status")
}
}
}
}
@main
struct MyApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
I tested with iOS 16 and 17, and it works as expected. But when I tested on iOS 18 emulator, the prompt appears, click on the Allow
or Not Allow
, and it froze. The user choice is still registered as ATT: User authorized tracking
show in the log (and after exit the app and open again, the log still show the correct user ATT choice).
The problem is relating to thread assertion issue. For example:
Thread 2 Queue : com.apple.root.default-qos (concurrent)
#0 0x00000001023e4214 in _dispatch_assert_queue_fail ()
#12 0x00000001025afb38 in _pthread_wqthread ()
My solution: After trying to debug, I found out that I only need to switch from Swift 6
to Swift 5
. And the application works again.
My Request: My request is that I still want to build the app with Swift 6
(for future proof purposes), how can I do so? Thanks~
1 Answer
Reset to default 0Thanks to Sweeper
for the solution. To fix, I updated the code like this:
func requestIDFA() {
Task { @MainActor in
let status = await ATTrackingManager.requestTrackingAuthorization()
handleATTStatus(status)
}
}
func handleATTStatus(_ status: ATTrackingManager.AuthorizationStatus) {
switch status {
case .authorized:
print("ATT: User authorized tracking")
case .denied:
print("ATT: User denied tracking")
case .restricted:
print("ATT: Tracking is restricted")
case .notDetermined:
print("ATT: User has not made a choice")
@unknown default:
print("ATT: Unknown status")
}
}
async
version ofrequestTrackingAuthorization
? I know some of the closure-based apis are not ready for Swift 6 yet. – Sweeper Commented Mar 30 at 11:24