最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

xcode - SwiftUI app freezes on iOS 18 with Swift 6 after ATT permission dialog clicked - thread assertion issue - Stack Overflow

programmeradmin0浏览0评论

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~

Share Improve this question asked Mar 30 at 10:58 vinhDev3006vinhDev3006 711 silver badge6 bronze badges 2
  • 1 Have you tried calling the async version of requestTrackingAuthorization? I know some of the closure-based apis are not ready for Swift 6 yet. – Sweeper Commented Mar 30 at 11:24
  • It actually works, thank you very much. – vinhDev3006 Commented Mar 30 at 12:05
Add a comment  | 

1 Answer 1

Reset to default 0

Thanks 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")
    }
}

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论