2つの個別のnavigationcontrollers
があり、1つはRootViewController
Aで、もう1つはRootViewController
Bです。
ViewController
CをAまたはBのナビゲーションスタックにプッシュできます。
質問:ViewController
Cにいるとき、AまたはBに属するスタックにいるかどうかを確認するにはどうすればよいですか?
UINavigationController
のviewControllers
プロパティを使用できます。
@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であるかどうかをテストできます。
受け入れられた答えの実装は次のとおりです。
- (UIViewController *)backViewController
{
NSInteger numberOfViewControllers = self.navigationController.viewControllers.count;
if (numberOfViewControllers < 2)
return nil;
else
return [self.navigationController.viewControllers objectAtIndex:numberOfViewControllers - 2];
}
- (UIViewController *)backViewController
{
NSInteger myIndex = [self.navigationController.viewControllers indexOfObject:self];
if ( myIndex != 0 && myIndex != NSNotFound ) {
return [self.navigationController.viewControllers objectAtIndex:myIndex-1];
} else {
return nil;
}
}
受け入れられた答えのより一般的な実装:
- (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;
}
これにより、現在のクラスがナビゲーションスタックのどこにあるかに関係なく、正しい「バックビューコントローラー」が返されます。
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
}
}
以下は、 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
}
}
UINavigationController
拡張として:
extension UINavigationController {
func previousViewController() -> UIViewController? {
guard viewControllers.count > 1 else {
return nil
}
return viewControllers[viewControllers.count - 2]
}
}
viewControllers
プロパティのn-2
要素にアクセスして、親View Controllerにアクセスします。
そのインスタンスを取得したら、 NSStringFromClass()
関数から出力される内容をログに記録して、そのタイプを確認できます。または、コントローラAとBにstatic const
識別子文字列と、文字列を出力するゲッター関数を保持することもできます。
@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
}
navigationController
メソッドを使用して取得します。 Appleのサイトのドキュメント を参照してください。
navigationControllerNavigation Controllerである親または祖先。 (読み取り専用)
@property(nonatomic、readonly、retain)UINavigationController * navigationController
DiscussionView Controllerがスタックにある場合にのみNavigation Controllerを返します。 Navigation Controllerが見つからない場合、このプロパティはnilです。
可用性iOS 2.0以降で利用可能。
死んだ馬は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];
}
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
}
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に置き換えるだけです。
前のView Controllerを見つけるのは簡単です。
あなたの場合、つまり、あなたはCにいて、Bが必要です。[self.navigationController.viewControllers lastObject]
はあなたが望むものです。
Aの場合、AはルートView Controllerであるため、lastObject
をfirstObject
に置き換えるだけで取得できます。
ガードを使用して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]
}
}
より簡潔な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]
}
}
私の拡張機能、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
}
}
}