按下后退按钮时如何跳过上一个视图

时间:2016-06-05 00:47:32

标签: ios swift model-view-controller uinavigationcontroller

我的导航为:

List of Friends with messages Controller(点击撰写) - > List of friends to select chatting(选择朋友) - > Show chat with friend

目前,如果在Show chat with friend内且用户选择back,则会将其带到List of friends to select chatting控制器。 我希望跳过此控制器,并在返回选择后导航到List of Friends with messages Controller

注意:List of Friends with messages Controller是嵌入在标签中的。

我尝试在self.navigationController?.viewControllers.removeLast()之间的segue内使用List of friends to select chatting将其从堆栈中删除。但是在导航到Show chat with friend之后,后退按钮消失了......

如何允许我描述的导航?

4 个答案:

答案 0 :(得分:3)

如果您的目标是跳过第二个UIViewController并从第三个UIViewController回到第一个UIViewController。请尝试以下代码:

// This count will return how many view controllers are there in navigation stack
let controllersInNavigationCount = self.navigationController?.viewControllers.count

// This will pop to first UIViewController skipping second UIViewController
self.navigationController?.popToViewController(self.navigationController?.viewControllers[controllersInNavigationCount!-2] as! FirstViewController, animated: true)

答案 1 :(得分:0)

这有点棘手。我如何处理这个问题是

  • 在ViewWillAppear下显示与朋友View Controller的聊天时,我会设置一个名为pageViewed的NSUserDefault,并将其值设置为1.

  • 现在在朋友列表中选择聊天ViewWillAppear下的View Controller我会查看pageViewed NSUserDefault的值是否为1.如果是,则将其设置为0并调用make a将其从堆栈中删除。

//Remove from Nav-Stack
[self.navigationController popViewControllerAnimated:YES];

再次它有点棘手,但绝对可行。

答案 2 :(得分:0)

Xcode 7.2.1
iOS 9.2
斯威夫特2.1.1
OSX 10.10.5

以下对我有用:

  1. 您可以在循环中使用navigationController?.popViewControllerAnimated(true)来跳过任意数量的视图控制器。

  2. 如果要返回的ViewController是UINavigationController堆栈中的第一个ViewController,则可以使用navigationController?.popToRootViewControllerAnimated(true)返回第一个视图控制器。

  3. 该应用程序仍然通过跳过的ViewController进行动画处理,因此您可以在前往目标ViewController的途中看到跳过的View幻灯片。

      

    我尝试过使用:   self.navigationController?.viewControllers.removeLast(),在   朋友列表之间的segue选择聊天删除它   从堆栈。但之后导航到Show聊天   朋友,后退按钮消失......

    嗯......好像应该有用。从前一个ViewController的navigationItem属性中检索后退按钮信息。之前的ViewController navigationItem.backBarButtonItem包含您看到的后退按钮的信息。那么,当您从堆栈中删除ViewController时,为什么UINavigationController不会从早期的ViewController中检索navigationItem.backBarButtonItem信息?

    听起来目标ViewController可能已经获得了对前一个ViewController的弱引用 - 你从堆栈中删除的那个。然后,当您从viewControllers数组中删除以前的ViewController时,前一个ViewController消失了,弱引用被指定为nil - 这阻止了目标ViewController获取后退按钮的信息;因此没有显示后退按钮。

    <强> AppDelegate.swift

    //
    //  AppDelegate.swift
    //  NavigationBarExample
    //
    //  Copyright © 2016 7stud. All rights reserved.
    //
    
    import UIKit
    
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
    
        var window: UIWindow?
    
    
        func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
            // Override point for customization after application launch.
    
            let navController = window!.rootViewController as! UINavigationController
            let friendsController = navController.topViewController as! FriendsTableViewController
            friendsController.friendStore = FriendStore(names: ["Joe", "Cathy", "Bobo"])
    
            return true
        }
    
    ...
    ...
    

    <强> FriendsTableViewController.swift

    //  FriendsTableViewController.swift
    //  NavigationBarExample
    //
    //
    //  Copyright © 2016 7stud. All rights reserved.
    //
    
    import UIKit
    
    class FriendsTableViewController: UITableViewController {
        var friendStore: FriendStore!
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            //Prevent TableView from underlapping the status bar:
            let statusBarHeight = UIApplication.sharedApplication().statusBarFrame.height
            let insets = UIEdgeInsets(
                top: statusBarHeight, left: 0, bottom: 0, right: 0
            )
            tableView.contentInset = insets
            tableView.scrollIndicatorInsets = insets
        }
    
        //MARK: - UITableViewDataSource methods:
    
        override func tableView(tableView: UITableView,
            numberOfRowsInSection section: Int)
            -> Int
        {
            return friendStore.allFriends.count
        }
    
        override func tableView(tableView: UITableView,
            cellForRowAtIndexPath
            indexPath: NSIndexPath)
            -> UITableViewCell
        {
            let friend = friendStore.allFriends[indexPath.row]
    
            let cell = tableView.dequeueReusableCellWithIdentifier(
                "UITableViewCell-Default",
                forIndexPath: indexPath
            )
            cell.textLabel?.text = friend.name
    
            return cell
        }
    
        //MARK: - Segue:
    
        override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    
            if segue.identifier == "ShowFriend" {
                if let row = tableView.indexPathForSelectedRow?.row {
                    let viewController2 = segue.destinationViewController as! ViewController2
                    viewController2.friend = friendStore.allFriends[row]
                    viewController2.previousTitle = navigationItem.title
                }
    
    
            }
        }
    
    }
    

    <强> FriendStore.swift

    //
    //  FriendStore.swift
    //  NavigationBarExample
    //
    //  Copyright © 2016 7stud. All rights reserved.
    //
    
    import Foundation
    
    class FriendStore {
    
        var allFriends: [Friend] = []
    
        init(names: [String]) {
            for name in names {
                allFriends.append(Friend(name: name) )
            }
        }
    }
    

    <强> Friend.swift

    //
    //  Friend.swift
    //  NavigationBarExample
    //
    //  Copyright © 2016 7stud. All rights reserved.
    //
    
    import Foundation
    
    class Friend: NSObject {
        var name: String
    
        init(name: String) {
            self.name = name
    
            super.init()
        }
    
    }
    

    <强> ViewController2.swift

    //
    //  ViewController2.swift
    //  NavigationBarExample
    //
    //  Copyright © 2016 7stud. All rights reserved.
    //
    
    import UIKit
    
    class ViewController2: UIViewController {
        var friend: Friend! {
            didSet {
                navigationItem.title = friend.name
            }
        }
    
        var previousTitle: String!
    
        override func viewDidLoad() {
            //Set the correct title for the back button on the next view controller:
            let myBackButtonItem = UIBarButtonItem(
                title: previousTitle,
                style: .Plain,
                target: nil,
                action: nil  //An action specified here won't get called--I
                             //think the NavigationController must overwrite this sometime later.
            )
    
            navigationItem.backBarButtonItem = myBackButtonItem
    
        }
    }
    

    <强> ViewController3.swift

    //
    //  ViewController3.swift
    //  NavigationBarExample
    //
    //  Copyright © 2016 7stud. All rights reserved.
    //
    
    import UIKit
    
    class ViewController3: UIViewController {
    
        override func viewWillDisappear(animated: Bool) {
            super.viewWillDisappear(animated)
    
            let goBackCount = 2
    
            if let navController = navigationController {
                let viewControllers = navController.viewControllers
    
                if viewControllers.count >= goBackCount {
                    for _ in 1...goBackCount {
                        navController.popViewControllerAnimated(true)
                    }
    
                }
            }
        }
    }
    

    完成同样事情的一般方法是:如果要返回的控制器是根ViewController,即它是UINavigationController堆栈中的第一个控制器,那么在viewWillDisappear()你只需拨打navigationController?.popToRootViewControllerAnimated(true)

    即可

    Main.storyboard: enter image description here 在故事板中创建Table View后,我选择了Table View,在Xcode菜单栏中,我选择了Editor>Embed In>NavigationControllerNavigation Controllerinitial view controller。我还双击了Table View导航栏的中间位置,并将标题设置为Friends

    然后我控制+从Prototype Cell中的Table View拖动到View Controller2;从我选择的弹出窗口Selection Segue->Show

    然后我控制+从View Controller2的按钮拖动到View Controller3;从我选择的弹出窗口Action Segue->Show

答案 3 :(得分:0)

返回N个视图控制器的最佳方法是使用navigationController.viewControllers。当您到达最后一个viewController时,将删除N个以前的viewController,如下所示:

let previousViewControllerIndex = navigationController.viewControllers.count - N navigationController.viewControllers.remove(at: previousViewControllerIndex)

此后,当您按返回时,将导航到所需的控制器,而不会看到已删除的先前视图控制器的弹出动画。