UIViewController
にアクセスしないと、一番上のUINavigationController
を取得できないようです。これが私がこれまでに持っているものです:
UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(vc, animated: true, completion: nil)
しかし、何もしていないようです。 keyWindow
およびrootViewController
もnil以外の値であるように思われるので、オプションの連鎖は問題にならないはずです。
注:このようなことをするのは悪い考えです。 MVCパターンを破る
presentViewController
はビューコントローラを示します。 View Controllerを返しません。 UINavigationController
を使用していないのであれば、おそらくpresentedViewController
を探しているので、ルートから始めて表示されているビューを順に繰り返す必要があります。
if var topController = UIApplication.sharedApplication().keyWindow?.rootViewController {
while let presentedViewController = topController.presentedViewController {
topController = presentedViewController
}
// topController should now be your topmost view controller
}
Swift 3以降の場合:
if var topController = UIApplication.shared.keyWindow?.rootViewController {
while let presentedViewController = topController.presentedViewController {
topController = presentedViewController
}
// topController should now be your topmost view controller
}
この拡張子を持っている
Swift 2。*
extension UIApplication {
class func topViewController(controller: UIViewController? = UIApplication.sharedApplication().keyWindow?.rootViewController) -> UIViewController? {
if let navigationController = controller as? UINavigationController {
return topViewController(navigationController.visibleViewController)
}
if let tabController = controller as? UITabBarController {
if let selected = tabController.selectedViewController {
return topViewController(selected)
}
}
if let presented = controller?.presentedViewController {
return topViewController(presented)
}
return controller
}
}
Swift
extension UIApplication {
class func topViewController(controller: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let navigationController = controller as? UINavigationController {
return topViewController(controller: navigationController.visibleViewController)
}
if let tabController = controller as? UITabBarController {
if let selected = tabController.selectedViewController {
return topViewController(controller: selected)
}
}
if let presented = controller?.presentedViewController {
return topViewController(controller: presented)
}
return controller
}
}
あなたはあなたのコントローラのどこでもこれを使うことができます
if let topController = UIApplication.topViewController() {
}
Swift 4/5 +が最上位のviewControllerを取得するため
// MARK: UIApplication extensions
extension UIApplication {
class func getTopViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let nav = base as? UINavigationController {
return getTopViewController(base: nav.visibleViewController)
} else if let tab = base as? UITabBarController, let selected = tab.selectedViewController {
return getTopViewController(base: selected)
} else if let presented = base?.presentedViewController {
return getTopViewController(base: presented)
}
return base
}
}
使い方
if let topVC = UIApplication.getTopViewController() {
topVC.view.addSubview(forgotPwdView)
}
extension UIWindow {
func visibleViewController() -> UIViewController? {
if let rootViewController: UIViewController = self.rootViewController {
return UIWindow.getVisibleViewControllerFrom(vc: rootViewController)
}
return nil
}
static func getVisibleViewControllerFrom(vc:UIViewController) -> UIViewController {
if let navigationController = vc as? UINavigationController,
let visibleController = navigationController.visibleViewController {
return UIWindow.getVisibleViewControllerFrom( vc: visibleController )
} else if let tabBarController = vc as? UITabBarController,
let selectedTabController = tabBarController.selectedViewController {
return UIWindow.getVisibleViewControllerFrom(vc: selectedTabController )
} else {
if let presentedViewController = vc.presentedViewController {
return UIWindow.getVisibleViewControllerFrom(vc: presentedViewController)
} else {
return vc
}
}
}
}
使用法:
if let topController = window.visibleViewController() {
println(topController)
}
Objective-CバージョンDianzの回答に基づく
- (UIViewController *) topViewController {
UIViewController *baseVC = UIApplication.sharedApplication.keyWindow.rootViewController;
if ([baseVC isKindOfClass:[UINavigationController class]]) {
return ((UINavigationController *)baseVC).visibleViewController;
}
if ([baseVC isKindOfClass:[UITabBarController class]]) {
UIViewController *selectedTVC = ((UITabBarController*)baseVC).selectedViewController;
if (selectedTVC) {
return selectedTVC;
}
}
if (baseVC.presentedViewController) {
return baseVC.presentedViewController;
}
return baseVC;
}
https://Gist.github.com/db0company/369bfa43cb84b145dfd8 このサイトの回答とコメントについていくつかテストを行いました。私にとっては、次の作品
extension UIViewController {
func topMostViewController() -> UIViewController {
if let presented = self.presentedViewController {
return presented.topMostViewController()
}
if let navigation = self as? UINavigationController {
return navigation.visibleViewController?.topMostViewController() ?? navigation
}
if let tab = self as? UITabBarController {
return tab.selectedViewController?.topMostViewController() ?? tab
}
return self
}
}
extension UIApplication {
func topMostViewController() -> UIViewController? {
return self.keyWindow?.rootViewController?.topMostViewController()
}
}
次に、次のようにしてトップのviewControllerを取得します。
UIApplication.shared.topMostViewController()
このコードを使用して、最も上位にあるUIViewControllerを見つけます。
func getTopViewController() -> UIViewController? {
var topController: UIViewController? = UIApplication.shared.keyWindow?.rootViewController
while topController?.presentedViewController != nil {
topController = topController?.presentedViewController
}
return topController
}
私は大好きだった @ dianz's answer だから、これがSwift 3のバージョンです。それは基本的に同じことですが、彼は中括弧を欠いていて、構文/変数/メソッドの名前のいくつかは変更されました。だからここにあります!
extension UIApplication {
class func topViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let nav = base as? UINavigationController {
return topViewController(base: nav.visibleViewController)
}
if let tab = base as? UITabBarController {
if let selected = tab.selectedViewController {
return topViewController(base: selected)
}
}
if let presented = base?.presentedViewController {
return topViewController(base: presented)
}
return base
}
}
使い方はまだまったく同じです:
if let topController = UIApplication.topViewController() {
print("The view controller you're looking at is: \(topController)")
}
上記のBob-cに基づきます。
Swift 3.
extension UIWindow {
func visibleViewController() -> UIViewController? {
if let rootViewController: UIViewController = self.rootViewController {
return UIWindow.getVisibleViewControllerFrom(vc: rootViewController)
}
return nil
}
class func getVisibleViewControllerFrom(vc:UIViewController) -> UIViewController {
if vc.isKind(of: UINavigationController.self) {
let navigationController = vc as! UINavigationController
return UIWindow.getVisibleViewControllerFrom( vc: navigationController.visibleViewController!)
} else if vc.isKind(of: UITabBarController.self) {
let tabBarController = vc as! UITabBarController
return UIWindow.getVisibleViewControllerFrom(vc: tabBarController.selectedViewController!)
} else {
if let presentedViewController = vc.presentedViewController {
return UIWindow.getVisibleViewControllerFrom(vc: presentedViewController)
} else {
return vc;
}
}
}
}
関数ではなく計算変数を使用した@AlberZouのわずかな変化
extension UIViewController {
var topMostViewController : UIViewController {
if let presented = self.presentedViewController {
return presented.topMostViewController
}
if let navigation = self as? UINavigationController {
return navigation.visibleViewController?.topMostViewController ?? navigation
}
if let tab = self as? UITabBarController {
return tab.selectedViewController?.topMostViewController ?? tab
}
return self
}
}
extension UIApplication {
var topMostViewController : UIViewController? {
return self.keyWindow?.rootViewController?.topMostViewController
}
}
それから言う
if let topViewControler = UIApplication.shared.topMostViewController {
... do stuff
}
Swift 3で可視のviewControllerを見つけるには
if let viewControllers = window?.rootViewController?.childViewControllers {
let prefs = UserDefaults.standard
if viewControllers[viewControllers.count - 1] is ABCController{
print("[ABCController] is visible")
}
}
このコードは、最後に追加されたコントローラ、または最後にアクティブになったコントローラを表示します。
これはAppDelegateでアクティブなView Controllerを見つけるために使用しました
appDelegateでUIViewController変数を定義し、すべてのviewWillAppearで変数をselfに設定することができます(ただし、dianzの回答が最良の回答です)。
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
let appDel = UIApplication.sharedApplication().delegate as! AppDelegate
appDel.currentVC = self
}
フレーバーが多すぎますが、反復的なものではありませんでした。前のものと組み合わせて:
func topMostController() -> UIViewController? {
var from = UIApplication.shared.keyWindow?.rootViewController
while (from != nil) {
if let to = (from as? UITabBarController)?.selectedViewController {
from = to
} else if let to = (from as? UINavigationController)?.visibleViewController {
from = to
} else if let to = from?.presentedViewController {
from = to
} else {
break
}
}
return from
}
ごくまれに、カスタムセグエで、最上位のView ControllerがナビゲーションスタックまたはTab Bar Controllerに含まれていないか表示されていないが、そのビューが主要なWindownのサブビューの最上位に挿入されている。
このような状況では、現在のView Controllerが最上位であるかどうかを判断するためにUIApplication.shared.keyWindow.subviews.last == self.view
を確認する必要があります。
どこにコードを入れましたか?
私のデモであなたのコードを試してみます。
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
キーウィンドウはまだ設定されているので失敗します。
しかし、私はあなたのコードをいくつかのView Controllerに入れます。
override func viewDidLoad() {
それだけでうまくいきます。
私にとって最良の解決策は、機能を備えた拡張機能です。この拡張子を持つSwiftファイルを作成します
最初はUIWindow拡張機能です:
public extension UIWindow {
var visibleViewController: UIViewController? {
return UIWindow.visibleVC(vc: self.rootViewController)
}
static func visibleVC(vc: UIViewController?) -> UIViewController? {
if let navigationViewController = vc as? UINavigationController {
return UIWindow.visibleVC(vc: navigationViewController.visibleViewController)
} else if let tabBarVC = vc as? UITabBarController {
return UIWindow.visibleVC(vc: tabBarVC.selectedViewController)
} else {
if let presentedVC = vc?.presentedViewController {
return UIWindow.visibleVC(vc: presentedVC)
} else {
return vc
}
}
}
}
そのファイル内で関数を追加
func visibleViewController() -> UIViewController? {
let appDelegate = UIApplication.shared.delegate
if let window = appDelegate!.window {
return window?.visibleViewController
}
return nil
}
また、使用したい場合は、どこでも呼び出すことができます。 例:
override func viewDidLoad() {
super.viewDidLoad()
if let topVC = visibleViewController() {
//show some label or text field
}
}
ファイルコードは次のようになります:
import UIKit
public extension UIWindow {
var visibleViewController: UIViewController? {
return UIWindow.visibleVC(vc: self.rootViewController)
}
static func visibleVC(vc: UIViewController?) -> UIViewController? {
if let navigationViewController = vc as? UINavigationController {
return UIWindow.visibleVC(vc: navigationViewController.visibleViewController)
} else if let tabBarVC = vc as? UITabBarController {
return UIWindow.visibleVC(vc: tabBarVC.selectedViewController)
} else {
if let presentedVC = vc?.presentedViewController {
return UIWindow.visibleVC(vc: presentedVC)
} else {
return vc
}
}
}
}
func visibleViewController() -> UIViewController? {
let appDelegate = UIApplication.shared.delegate
if let window = appDelegate!.window {
return window?.visibleViewController
}
return nil
}
var topViewController: UIViewController? {
guard var topViewController = UIApplication.shared.keyWindow?.rootViewController else { return nil }
while let presentedViewController = topViewController.presentedViewController {
topViewController = presentedViewController
}
return topViewController
}