主线程调用方法触发UI无响应警告,Admob启动代码位置是否合理?
问题
- 主线程收到错误提示:
"This method should not be called on the main thread as it may lead to UI unresponsiveness." - 多数场景UI响应正常,但偶尔出现无响应,尤其是使用
Link()跳转APP外部链接时,怀疑是新增的Google AdMob代码导致。 - 相关代码:
import SwiftUI import BackgroundTasks import GoogleMobileAds import UserNotifications @main struct Test_ProjectApp: App { init(){ GADMobileAds.sharedInstance().start(completionHandler: nil) let isNotificationsEnabled = UserDefaults.standard.bool(forKey: "isNotificationsEnabled") if isNotificationsEnabled { UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in if granted { print("Notifications permission granted.") exampleNotification() } else { print("Notifications permission denied because: \(error?.localizedDescription ?? "unknown error").") } } } } var body: some Scene { WindowGroup { ContentView() .onOpenURL(perform: { url in }) } } }
回答
当前调用GADMobileAds.sharedInstance().start()的位置不合适,必须调整。
原因
App的init()方法运行在主线程,而GADMobileAds.start()属于可能耗时的初始化操作,会阻塞主线程,这正是错误提示的来源,也是你偶尔遇到UI无响应的核心诱因。
调整方案
将AdMob的初始化逻辑移到后台线程执行,避免占用主线程资源:
import SwiftUI import BackgroundTasks import GoogleMobileAds import UserNotifications @main struct Test_ProjectApp: App { init(){ // 后台线程初始化AdMob,避免阻塞主线程 DispatchQueue.global(qos: .background).async { GADMobileAds.sharedInstance().start(completionHandler: nil) } let isNotificationsEnabled = UserDefaults.standard.bool(forKey: "isNotificationsEnabled") if isNotificationsEnabled { UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in if granted { print("Notifications permission granted.") // 若exampleNotification()涉及UI操作,必须切回主线程执行 DispatchQueue.main.async { exampleNotification() } } else { print("Notifications permission denied because: \(error?.localizedDescription ?? "unknown error").") } } } } var body: some Scene { WindowGroup { ContentView() .onOpenURL(perform: { url in }) } } }
额外注意
- 如果
exampleNotification()包含UI相关操作(比如更新界面状态、弹出提示),必须放在DispatchQueue.main.async中执行,因为通知权限的回调默认在后台线程运行。 - 后续新增的AdMob相关初始化操作,都优先放在后台线程完成,仅将UI交互逻辑切回主线程。
内容的提问来源于stack exchange,提问作者Mxyb
相关产品推荐
相关产品推荐

