草庐IT

ios - 如何以编程方式重新排序我的 UINavigationController 项目?

coder 2023-09-05 原文

在我的 TabBarViewController 中,我正在创建一个导航并以模态方式呈现它。

func viewDidLoad(){ 
    super.viewDidLoad();
    //Create a present this view controller in viewDidLoad
    self.navController =  UINavigationController() 
    self.presentViewController(self.navController, animated: true, completion: nil)
}

//This method gets called when TabBarVC gets a NSNotification
func showMessageForUser(user_id: Int){
    let mvc = self.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! MessagesViewController
    mvc.user_id = user_id //set this user

    //display this to the user.
    self.navController.pushViewController(mvc, animated: true)
}

这很简单。但是,我想这样做:

  • 如果 user_id 已经在堆栈中,将其移动到堆栈的末尾,以便用户可以看到它。没有重复。我该怎么做?
  • 否则,只需创建一个新的 View Controller 实例并将其添加到堆栈的顶部。我想我已经在上面这样做了。

重新排序后,所有“后退”按钮都应按预期工作。

最佳答案

您可以使用 setViewControllers(_:animated:) 重新排列 View Controller 堆栈。您无需执行任何特殊操作即可使后退按钮正常工作。导航 Controller 根据其 viewControllers 数组中的第二项设置后退按钮(如果有第二项),并在更新 viewControllers 时更新后退按钮数组。

下面是我将如何做到这一点。首先,我们向 UIViewController 添加一个方法来询问它是否是特定 userId 的 View Controller 。由于大多数 View Controller 不是(也不可能是)正确的 View Controller ,它只返回 false:

extension UIViewController {
    func isViewControllerForUserId(userId: Int) -> Bool {
        return false
    }
}

然后我们在 MessagesViewController 中覆盖此方法以在适当的时候返回 true:

extension MessagesViewController {
    override func isViewControllerForUserId(userId: Int) -> Bool {
        return self.userId == userId
    }
}

现在,为了向特定用户显示 View Controller ,我们在导航 Controller 的堆栈中搜索现有的 View Controller 。我们采取的行动取决于我们是否找到它:

func showMessageForUserId(userId: Int) {
    if let index = navController.viewControllers.indexOf({ $0.isViewControllerForUserId(userId) }) {
        navController.moveToTopOfNavigationStack(viewControllerAtIndex: index)
    } else {
        pushNewViewControllerForUserId(userId)
    }
}

如果我们没有找到它,我们会创建一个新的 View Controller 并推送它:

    private func pushNewViewControllerForUserId(userId: Int) {
        let vc = self.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! MessagesViewController
        vc.userId = userId
        self.navController.pushViewController(vc, animated: true)
    }

如果我们确实找到了它,我们就用这个方法把它移到导航栈的顶部:

extension UINavigationController {

    func moveToTopOfNavigationStack(viewControllerAtIndex index: Int) {
        var stack = viewControllers
        if index == stack.count - 1 {
            // nothing to do because it's already on top
            return
        }
        let vc = stack.removeAtIndex(index)
        if (reorderingIsBuggy) {
            setViewControllers(stack, animated: false)
        }
        stack.append(vc)
        setViewControllers(stack, animated: true)
    }

    private var reorderingIsBuggy: Bool {
        // As of iOS 9.3 beta 3, `UINavigationController` drops the prior top-of-stack
        // when you use `setViewControllers(_:animated:)` to move a lower item to the
        // top with animation. The workaround is to remove the lower item from the stack
        // without animation, then add it to the top of the stack with animation. This
        // makes it display a push animation instead of a pop animation and avoids
        // dropping the prior top-of-stack.
        return true
    }

}

关于ios - 如何以编程方式重新排序我的 UINavigationController 项目?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35400795/

有关ios - 如何以编程方式重新排序我的 UINavigationController 项目?的更多相关文章

  1. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  2. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  3. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  4. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  5. ruby-on-rails - active_admin 目录中的常量警告重新声明 - 2

    我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA

  6. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  7. ruby-on-rails - 新 Rails 项目 : 'bundle install' can't install rails in gemfile - 2

    我已经像这样安装了一个新的Rails项目:$railsnewsite它执行并到达:bundleinstall但是当它似乎尝试安装依赖项时我得到了这个错误Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcheckingforlibkern/OSAtomic.h...yescreatingMakefilemake"DESTDIR="cleanmake"DESTDIR="

  8. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  9. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  10. ruby-on-rails - 正确的 Rails 2.1 做事方式 - 2

    question的一些答案关于redirect_to让我想到了其他一些问题。基本上,我正在使用Rails2.1编写博客应用程序。我一直在尝试自己完成大部分工作(因为我对Rails有所了解),但在需要时会引用Internet上的教程和引用资料。我设法让一个简单的博客正常运行,然后我尝试添加评论。靠我自己,我设法让它进入了可以从script/console添加评论的阶段,但我无法让表单正常工作。我遵循的其中一个教程建议在帖子Controller中创建一个“评论”操作,以添加评论。我的问题是:这是“标准”方式吗?我的另一个问题的答案之一似乎暗示应该有一个CommentsController参

随机推荐