it-swarm.com.de

So identifizieren Sie den vorherigen View-Controller im Navigationsstapel

Ich habe 2 getrennte navigationcontrollers, eine mit RootViewController A und die andere mit RootViewController B.

Ich kann ViewController C auf den Navigationsstapel von A oder B schieben.

Frage: Wenn ich in ViewController C bin, wie kann ich herausfinden, ob ich im Stack von A oder B bin?

77
Zhen

Sie können die UINavigationController -Eigenschaft von viewControllers verwenden:

@property(nonatomic, copy) NSArray *viewControllers

Diskussion: Der Root-View-Controller befindet sich im Array auf Index 0, der Back-View-Controller auf Index n-2 und der Top-Controller auf Index n-1, wobei n die Anzahl der Elemente im Array ist.

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

Sie können damit testen, ob der Root-View-Controller (der mit dem Array-Index 0) View-Controller A oder B ist.

106
jburns20

Hier ist die Umsetzung der akzeptierten Antwort:

- (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

Eine allgemeinere Implementierung der akzeptierten Antwort:

- (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;
}

Dies gibt den richtigen "Rückansicht-Controller" zurück, unabhängig davon, wo sich die aktuelle Klasse auf dem Navigationsstapel befindet.

11
tjklemz

Schnelle Implementierung von tjklemz code als Erweiterung:

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

Hier ist eine modifizierte Version von Prabhu Beemans Swift-Code, der ihn an Swift 3 anpasst:

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

Als UINavigationController-Erweiterung: 

extension UINavigationController {

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

}
3
Adam Johns

Greifen Sie auf das n-2-Element der viewControllers -Eigenschaft zu, um auf den übergeordneten View-Controller zuzugreifen.

Sobald Sie diese Instanz haben, können Sie deren Typ überprüfen, indem Sie protokollieren, was aus der Funktion NSStringFromClass() hervorgeht. Oder Sie können einen static const-Bezeichnerstring in den Controllern A und B und eine Getter-Funktion, die den String ausgibt, behalten. 

3
Alex Reynolds

Schnelle Implementierung von @tjklemz-Code:

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

Verwenden Sie die navigationController-Methode, um sie abzurufen. Siehe Dokumentation auf der Apple-Website .

navigationController Ein übergeordneter oder Vorfahr, bei dem es sich um eine Navigation handelt Regler. (schreibgeschützt)

@ property (nonatomic, readonly, keep) UINavigationController * navigationController

Diskussion Gibt nur einen Navigationscontroller zurück, wenn die Ansicht Controller ist in seinem Stapel. Diese Eigenschaft ist null, wenn eine Navigation Controller kann nicht gefunden werden.

Verfügbarkeit Verfügbar in iOS 2.0 und höher.

1
Perception

Weil tote Pferde gerne geschlagen werden :)

- (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

Implementierung für Swift 2.2 - Fügen Sie dies in einer Erweiterung von UIViewController hinzu. Sicher in dem Sinne, dass es nil zurückgibt, wenn der Viewcontroller rootvc ist oder nicht in einem Navigationscontroller.

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

für Swift 3 Sie können dies tun:

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

Sie müssen lediglich "NameOfMyDestinationViewController" durch viewController ersetzen, den Sie zurückgeben möchten.

0
gandhi Mena

Den vorherigen View-Controller zu finden ist einfach. 

In Ihrem Fall, d. H., Sie befinden sich in C und benötigen B, [self.navigationController.viewControllers lastObject] ist das, was Sie wollen. 

Für A können Sie, da A der Root-View-Controller ist, einfach lastObject durch firstObject ersetzen.

0
chih-chun chan

Mit Swift mit Guard.

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

Eine prägnantere schnelle Aufbringung:

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

Meine Erweiterung, 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