1

目前我使用这种方法来获取当前的视图控制器:

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

所以我的问题是。是否有线程安全的方式来访问当前显示的视图控制器?

4

1 回答 1

0

从主线程访问是否适合您的需求?

func getTopThreadSafe(completion: @escaping(UIViewController?) -> Void) {
    DispatchQueue.main.async {
        let topMostVC: UIViewController = UIApplication.shared.keyWindow?.rootViewController?
        completion(topMostVC)
    }
}

这可能会有点令人困惑,因为它是一种异步方法,但我的直觉告诉我,无论你做什么,这都是最安全的选择:)

于 2017-10-12T20:59:48.767 回答