获取当前显示的视图控制器的线程安全方式
Thread safe way to get currently displayed view controller
目前我使用这个方法获取当前视图控制器:
func topMostContoller()-> UIViewController?{
if !Thread.current.isMainThread{
logError(message: "ACCESSING TOP MOST CONTROLLER OUTSIDE OF MAIN THREAD")
return nil
}
let topMostVC:UIViewController = UIApplication.shared.keyWindow!.rootViewController!
return topVCWithRootVC(topMostVC)
}
此方法从 rootViewController 开始遍历视图控制器的层次结构,直到到达顶部。
func topVCWithRootVC(_ rootVC:UIViewController)->UIViewController?{
if rootVC is UITabBarController{
let tabBarController:UITabBarController = rootVC as! UITabBarController
if let selectVC = tabBarController.selectedViewController{
return topVCWithRootVC(selectVC)
}else{
return nil
}
}else if rootVC.presentedViewController != nil{
if let presentedViewController = rootVC.presentedViewController! as UIViewController!{
return topVCWithRootVC(presentedViewController)
}else{
return nil
}
} else {
return rootVC
}
}
这个问题在 topMostController
中,因为它使用了不应在后台线程中使用的 UIApplication.shared.keyWindow
和 UIApplication.shared.keyWindow.rootViewController
。我收到这些警告:
runtime: UI API called from background thread: UIWindow.rootViewController must be used from main thread only
runtime: UI API called from background thread: UIApplication.keyWindow must be used from main thread only
所以我的问题是。是否有线程安全的方法来访问当前显示的视图控制器?
从主线程访问是否适合您的需要?
func getTopThreadSafe(completion: @escaping(UIViewController?) -> Void) {
DispatchQueue.main.async {
let topMostVC: UIViewController = UIApplication.shared.keyWindow?.rootViewController?
completion(topMostVC)
}
}
这可能会有点令人困惑,因为它是一种异步方法,但我的直觉告诉我,无论您要做什么,这都是最安全的选择:)
目前我使用这个方法获取当前视图控制器:
func topMostContoller()-> UIViewController?{
if !Thread.current.isMainThread{
logError(message: "ACCESSING TOP MOST CONTROLLER OUTSIDE OF MAIN THREAD")
return nil
}
let topMostVC:UIViewController = UIApplication.shared.keyWindow!.rootViewController!
return topVCWithRootVC(topMostVC)
}
此方法从 rootViewController 开始遍历视图控制器的层次结构,直到到达顶部。
func topVCWithRootVC(_ rootVC:UIViewController)->UIViewController?{
if rootVC is UITabBarController{
let tabBarController:UITabBarController = rootVC as! UITabBarController
if let selectVC = tabBarController.selectedViewController{
return topVCWithRootVC(selectVC)
}else{
return nil
}
}else if rootVC.presentedViewController != nil{
if let presentedViewController = rootVC.presentedViewController! as UIViewController!{
return topVCWithRootVC(presentedViewController)
}else{
return nil
}
} else {
return rootVC
}
}
这个问题在 topMostController
中,因为它使用了不应在后台线程中使用的 UIApplication.shared.keyWindow
和 UIApplication.shared.keyWindow.rootViewController
。我收到这些警告:
runtime: UI API called from background thread: UIWindow.rootViewController must be used from main thread only
runtime: UI API called from background thread: UIApplication.keyWindow must be used from main thread only
所以我的问题是。是否有线程安全的方法来访问当前显示的视图控制器?
从主线程访问是否适合您的需要?
func getTopThreadSafe(completion: @escaping(UIViewController?) -> Void) {
DispatchQueue.main.async {
let topMostVC: UIViewController = UIApplication.shared.keyWindow?.rootViewController?
completion(topMostVC)
}
}
这可能会有点令人困惑,因为它是一种异步方法,但我的直觉告诉我,无论您要做什么,这都是最安全的选择:)