【问题标题】:How to Skip Over Previous View When Back Button Pressed按下后退按钮时如何跳过上一个视图
【发布时间】:2016-10-04 19:40:12
【问题描述】:

我的导航是:

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 是嵌入在选项卡中的。

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

如何允许我描述的导航?

【问题讨论】:

  • 您的想法是正确的,但我建议您修改 viewWillAppear 中的 self.navigationController?.viewControllers 数组,以运行您的 show chat with friend 视图控制器。请注意,在这种情况下,您不能只使用 removeLast。您将不得不删除元素 count-2
  • 使用委托、通知来执行此操作。
  • 相信stackoverflow.com/questions/18824186/…这里的答案会对你有所帮助。
  • @axel 哪里有快速翻译?
  • 提供的答案中有

标签: ios swift model-view-controller uinavigationcontroller


【解决方案1】:

如果您的目标是跳过第二个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)

【讨论】:

    【解决方案2】:

    这有点棘手。我将如何解决这个问题是

    • 在 viewWillAppear 下的 Show chat withfriend View Controller 中,我将设置一个名为 pageViewed 的 NSUserDefault 并将其值设置为 1。

    • 现在在朋友列表中选择 viewWillAppear 下的聊天视图控制器我会检查 pageViewed NSUserDefault 的值是否为 1。如果将其设置回 0 并调用 make a 将其从堆栈中删除.

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

    同样,它有点棘手,但绝对可行。

    【讨论】:

    • 使用 unwindForSegue(unwindSegue: UIStoryboardSegue, 朝向ViewController: UIViewController)
    • @jjtalie,展开转场有更好的效果:您不会在通往目标控制器的途中通过中间控制器进行动画处理,但据我所知,您无法连接将 segue(或任何其他操作)展开到导航栏的后退按钮。如果 op 愿意用自定义按钮替换后退按钮,或者在第三个控制器的界面中添加一个额外的按钮,那么 unwind segue 似乎是一个很好、简单的解决方案。
    【解决方案3】:

    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) 返回第一个视图控制器。

    应用仍然通过跳过的 ViewController 进行动画处理,因此您会看到跳过的 View 在到达目标 ViewController 的途中滑过。

    我尝试过使用: self.navigationController?.viewControllers.removeLast(),在 在朋友列表之间切换以选择聊天以将其删除 从堆栈中。但是在导航到 Show chat with 之后 朋友,后退按钮消失了……

    嗯......这似乎应该工作。后退按钮信息是从前一个 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: 在情节提要中创建Table View 后,我选择了Table View,在Xcode 菜单栏中,我选择了Editor>Embed In>NavigationControllerNavigation Controllerinitial view controller。我还双击导航栏中间的Table View,并将标题设置为Friends

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

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

    【讨论】:

      【解决方案4】:

      返回 N 个视图控制器的最佳方法是使用 navigationController.viewControllers。当您到达最后一个 viewController 时,您会像这样删除 N 个之前的 viewController:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-12-23
        • 1970-01-01
        • 1970-01-01
        • 2011-01-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多