如何检查视图控制器是不是添加到堆栈中

Posted

技术标签:

【中文标题】如何检查视图控制器是不是添加到堆栈中【英文标题】:How to check viewcontroller is added in stack or not如何检查视图控制器是否添加到堆栈中 【发布时间】:2017-03-16 05:33:50 【问题描述】:

我有两个视图控制器。通过按下按钮使用下面的代码,我已经从一个视图导航到另一个视图。

 *let secondViewController = self.storyboard!.instantiateViewControllerWithIdentifier("NotificationController") as! NotificationController

self.navigationController!.pushViewController(secondViewController, animated: true)*

对于后面,我使用下面的代码在 bar 按钮上使用 bar button click for back。

 self.navigationController?.popViewControllerAnimated(true)

所以我的问题是,如果我不断地从一个视图转到另一个视图,那么它会添加到堆栈中。我只想显示另一个视图,当它已经添加到堆栈中以停止添加它。它只添加一次。

【问题讨论】:

***.com/a/42523549/5461400 试试这个 yourViewController.view.window != nil 【参考方案1】:

要检查导航堆栈是否包含特定类型的view controller,您可以使用:

if let viewControllers = self.navigationController?.viewControllers

    if viewControllers.contains(where: 
        return $0 is YourViewController
    )
    
        //Write your code here
    

要从导航堆栈中删除特定控制器,您需要对导航堆栈进行更改。

示例:

    if var viewControllers = self.navigationController?.viewControllers
    
        for controller in viewControllers
        
            if controller is UIViewController
            
                viewControllers.removeElement(controller)
                self.navigationController?.viewControllers = viewControllers
            
        
    

【讨论】:

Array 上没有 'removeElement()' 方法。但是您可以通过过滤 viewControllers 属性来执行相同的操作。请参阅我的答案以获取示例,并详细说明您的答案。干杯。【参考方案2】:

对于 swift 4,您可以使用

 if let viewControllers = self.navigationController?.viewControllers 
       for vc in viewControllers 
            if vc.isKind(of: YourViewController.classForCoder()) 
                 print("It is in stack")
                 //Your Process
            
       
 

【讨论】:

【参考方案3】:

针对 Swift 4.1 详细阐述 PGDev 的答案

如何从UINavigationController 堆栈中删除特定的UIViewController 子类:

/// Given 'nc' is a valid UINavigationController instance,
/// removes all instances of MyViewController from the stack

nc.viewControllers = nc.viewControllers.filter  !($0 is MyViewController) 

把它作为一个扩展:

extension UINavigationController

    /// Given the kind of a (UIViewController subclass),
    /// removes any matching instances from self's
    /// viewControllers array.

    func removeAnyViewControllers(ofKind kind: AnyClass)
    
        self.viewControllers = self.viewControllers.filter  !$0.isKind(of: kind)
    

    /// Given the kind of a (UIViewController subclass),
    /// returns true if self's viewControllers array contains at
    /// least one matching instance.

    func containsViewController(ofKind kind: AnyClass) -> Bool
    
        return self.viewControllers.contains(where:  $0.isKind(of: kind) )
    

用法:

guard let nc = self.navigationController else  return 

let exists = nc.containsViewController(ofKind: MyViewController.self)

nc.removeAnyViewControllers(ofKind: MyViewController.self)

顺便说一句,如果有人知道如何将 'kind' 限制在 UIViewController 的子类中,请大声说出来。

【讨论】:

func containsViewController(ofKind kind: UIViewController.Type) -> Bool return self.viewControllers.contains(where: $0.isKind(of: kind) ) 【参考方案4】:

这是检查它的代码。

if let viewControllers = navigationController?.viewControllers 
    for viewController in viewControllers 
        // some process
        if viewController.isKindOfClass(ViewControllerClassName) 
            println("yes it is")
        
     

【讨论】:

添加时如何在栈中移除 vc.removeFromParentViewController- 使用这个方法 如果你知道索引号,你也可以使用这个 self.navigationController?.viewControllers.removeAtIndex(vcIndex) 您觉得这有帮助吗? 当我再次从堆栈中移除时。它没有通过使用此代码添加到堆栈中。【参考方案5】:
extension UINavigationController 
    public func hasViewController(ofKind kind: AnyClass) -> UIViewController? 
        return self.viewControllers.first(where: $0.isKind(of: kind))
    

使用

self.navigationController.hasViewController(ofKind: #ViewControllerName#.self)

【讨论】:

【参考方案6】:

您可以通过以下code查看

目标 - C

NSArray * controllers = [self.navigationController viewControllers];

    for (int i = 0; i < [controllers count]; i++)

        UIViewController * controllerTest = [controllers objectAtIndex:i];

        if([controllerTest isKindOfClass:[YourController class]])
            NSLog(@"Class is available");
        

    

斯威夫特 3.0

if let viewControllers = self.navigationController?.viewControllers 
            for viewController in viewControllers 
                // some process
                if viewController.isKindOfClass(YourController) 
                    print("Class is available")
                
             
        

【讨论】:

如何在类可用时删除或仅显示而不添加堆栈【参考方案7】:

我们开始吧。

这一行会给你一个 UIViewControllers 数组

self.navigationController?.viewControllers

现在你要做的是检查你的 viewControllerObject 是否存在?

通过写这行

if viewController.isKindOfClass(YourController)

这是一个完整的代码。

if let viewControllers = self.navigationController?.viewControllers 
            for viewController in viewControllers 

                if viewController.isKindOfClass(YourController) 
                    print("Your controller exist")
                
        

当您在返回“ViewControllerA”时写下一行时,它将从导航堆栈中删除一个 ViewControllerB。

self.navigationController?.popViewControllerAnimated(true)

这与我们对堆栈进行的弹出操作类似,而导航控制器是一个堆栈。

如果您有任何困惑,请告诉我。

【讨论】:

【参考方案8】:

Swift 5(工作测试)。 检查视图控制器是否堆叠在导航中的更好方法是简单地询问视图控制器的可访问性。参见示例 下面。我使用这个 sn-p 回到以前的视图控制器。

    if self.navigationController?.accessibilityActivate() != nil 
        self.navigationController?.popViewController(animated: true)
     else 
        self.dismiss(animated: true, completion: nil)
    

【讨论】:

【参考方案9】:

这是另一个独奏:

    guard let controllersInStack = navigationController?.viewControllers else  return 
    if let yourViewController = controllersInStack.first(where:  $0 is YourViewController ) 
        // Do what you want with yourViewController
    

【讨论】:

【参考方案10】:

您只需检查视图控制器的 nibName 即可获得结果

下面的这段代码将确保您不会在 navigatoinController 中再次添加一个 viewController,

    var VC = YourViewController
    var objVC = (storyboard.instantiateViewController(withIdentifier: "YourViewController"))
    
if navigationController.viewControllers.contains(where:  (VC) -> Bool in
            return objVC.nibName == VC.nibName
        )
            for (i,controller) in navigationController.viewControllers.enumerated()
            
                if controller.isKind(of: VC)
                    navigationController.viewControllers.remove(at: i)
                    navigationController.pushViewController(objVC, animated: false)
                
            
        elsenavigationController.pushViewController(objVC, animated: false)

如果你只是想检查 viewController 是否在 NaviagtionController 中,那么试试这个:

var checkForView = navigationController.viewControllers.contains(where:  (VC) -> Bool in
            return objVC.nibName == VC.nibName
        )

【讨论】:

以上是关于如何检查视图控制器是不是添加到堆栈中的主要内容,如果未能解决你的问题,请参考以下文章

如何检查子视图控制器是不是存在

如何知道堆栈中都有哪些视图(或视图控制器)?

解决 Rails 3.2 中控制器的视图路径

如何展开到导航堆栈上的第一个视图控制器

是否存在 Modal ViewController: 将视图控制器添加到堆栈中?

iOS 7 在右侧添加了滑动以将视图控制器从堆栈中弹出。是不是可以通过向左滑动将其添加回来?