web-dev-qa-db-ja.com

Navigation Stackで以前のView Controllerを識別する方法

2つの個別のnavigationcontrollersがあり、1つはRootViewController Aで、もう1つはRootViewController Bです。

ViewController CをAまたはBのナビゲーションスタックにプッシュできます。

質問:ViewController Cにいるとき、AまたはBに属するスタックにいるかどうかを確認するにはどうすればよいですか?

78
Zhen

UINavigationControllerviewControllersプロパティを使用できます。

@property(nonatomic, copy) NSArray *viewControllers

議論:ルートView Controllerはアレイのインデックス0にあり、Back View Controllerはインデックスn-2にあり、トップコントローラはインデックスn-1にあります。nはアレイ内のアイテムの数です。

https://developer.Apple.com/documentation/uikit/uinavigationcontroller

これを使用して、ルートView Controller(配列インデックス0にあるもの)がView Controller AまたはBであるかどうかをテストできます。

106
jburns20

受け入れられた答えの実装は次のとおりです。

- (UIViewController *)backViewController
{
    NSInteger numberOfViewControllers = self.navigationController.viewControllers.count;

    if (numberOfViewControllers < 2)
        return nil;
    else
        return [self.navigationController.viewControllers objectAtIndex:numberOfViewControllers - 2];
}
102
George
- (UIViewController *)backViewController
{
    NSInteger myIndex = [self.navigationController.viewControllers indexOfObject:self];

    if ( myIndex != 0 && myIndex != NSNotFound ) {
        return [self.navigationController.viewControllers objectAtIndex:myIndex-1];
    } else {
        return nil;
    }
}
28
Chris

受け入れられた答えのより一般的な実装:

- (UIViewController *)backViewController {
    NSArray * stack = self.navigationController.viewControllers;

    for (int i=stack.count-1; i > 0; --i)
        if (stack[i] == self)
            return stack[i-1];

    return nil;
}

これにより、現在のクラスがナビゲーションスタックのどこにあるかに関係なく、正しい「バックビューコントローラー」が返されます。

11
tjklemz

tjklemz 拡張機能としてのコードの迅速な実装:

extension UIViewController {

    func backViewController() -> UIViewController? {        
        if let stack = self.navigationController?.viewControllers {
            for(var i=stack.count-1;i>0;--i) {
                if(stack[i] == self) {
                    return stack[i-1]
                }
            }
        }
        return nil
    }
}
9
grassyburrito

以下は、 Prabhu Beeman's Swiftコードの修正版で、Swift 3をサポートするように適応しています。

extension UIViewController {
    func backViewController() -> UIViewController? {
        if let stack = self.navigationController?.viewControllers {
            for i in (1..<stack.count).reverse() {
                if(stack[i] == self) {
                    return stack[i-1]
                }
            }
        }
        return nil
    }
}
9
Cin316

UINavigationController拡張として:

extension UINavigationController {

    func previousViewController() -> UIViewController? {
        guard viewControllers.count > 1 else {
            return nil
        }
        return viewControllers[viewControllers.count - 2]
    }

}
3
Adam Johns

viewControllers プロパティのn-2要素にアクセスして、親View Controllerにアクセスします。

そのインスタンスを取得したら、 NSStringFromClass() 関数から出力される内容をログに記録して、そのタイプを確認できます。または、コントローラAとBにstatic const識別子文字列と、文字列を出力するゲッター関数を保持することもできます。

3
Alex Reynolds

@tjklemzコードの迅速な実装:

var backViewController : UIViewController? {

        var stack = self.navigationController!.viewControllers as Array

        for (var i = stack.count-1 ; i > 0; --i) {
            if (stack[i] as UIViewController == self) {
                return stack[i-1] as? UIViewController
            }

        }
        return nil
    }
2
cdf1982

navigationControllerメソッドを使用して取得します。 Appleのサイトのドキュメント を参照してください。

navigationControllerNavigation Controllerである親または祖先。 (読み取り専用)

@property(nonatomic、readonly、retain)UINavigationController * navigationController

DiscussionView Controllerがスタックにある場合にのみNavigation Controllerを返します。 Navigation Controllerが見つからない場合、このプロパティはnilです。

可用性iOS 2.0以降で利用可能。

1
Perception

死んだ馬はbeatられて楽しむからです:)

- (UIViewController *)previousViewController
{
    NSArray *vcStack = self.navigationController.viewControllers;
    NSInteger selfIdx = [vcStack indexOfObject:self];
    if (vcStack.count < 2 || selfIdx == NSNotFound) { return nil; }
    return (UIViewController *)[vcStack objectAtIndex:selfIdx - 1];
}
1
Andrew

Swift 2.2の実装-これをUIViewController拡張に追加します。 viewcontrollerがrootvcか、navigationcontrollerにない場合、nilを返すという意味で安全です。

var previousViewController: UIViewController? {
  guard let viewControllers = navigationController?.viewControllers else {
    return nil
  }
  var previous: UIViewController?
  for vc in viewControllers{
    if vc == self {
      break
    }
    previous = vc
  }
  return previous
}
0
Blake Lockley

for Swiftこれを行うことができます:

var backtoViewController:UIViewController!
for viewController in (self.navigationController?.viewControllers)!.reversed() {
    if viewController is NameOfMyDestinationViewController {
            backtoViewController = viewController
    }
}
self.navigationController!.popToViewController(backtoViewController, animated: true)

「NameOfMyDestinationViewController」を、返したいviewControllerに置き換えるだけです。

0
gandhi Mena

前のView Controllerを見つけるのは簡単です。

あなたの場合、つまり、あなたはCにいて、Bが必要です。[self.navigationController.viewControllers lastObject]はあなたが望むものです。

Aの場合、AはルートView Controllerであるため、lastObjectfirstObjectに置き換えるだけで取得できます。

0
chih-chun chan

ガードを使用してSwiftで。

extension UIViewController {

    func getPreviousViewController() -> UIViewController? {
        guard let _ = self.navigationController else {
            return nil
        }

        guard let viewControllers = self.navigationController?.viewControllers else {
            return nil
        }

        guard viewControllers.count >= 2 else {
            return nil
        }        
        return viewControllers[viewControllers.count - 2]
    }
}
0
baquiax

より簡潔なSwift実装:

extension UIViewController {
    var previousViewController: UIViewController? {
        guard let nav = self.navigationController,
              let myIdx = nav.viewControllers.index(of: self) else {
            return nil
        }
        return myIdx == 0 ? nil : nav.viewControllers[myIdx-1]
    }
}
0
John Scalo

私の拡張機能、Swift 3

extension UIViewController {
    var previousViewController: UIViewController? {
        guard let controllers = navigationController?.viewControllers, controllers.count > 1 else { return nil }
        switch controllers.count {
        case 2: return controllers.first
        default: return controllers.dropLast(2).first
        }
    }
}
0
Dmytro Nasyrov