【问题标题】:Basic: Connecting multiple (View-)Controllers the right way基本:以正确的方式连接多个(视图-)控制器
【发布时间】:2014-09-12 17:43:17
【问题描述】:

我正在尝试设置一个登录屏幕 (ViewController),它会在成功登录后引导至用户列表 (UserTableViewController),该用户列表本身就是导航控制器的一部分。在随后的屏幕上,如UserTableViewController,应该可以注销。这将使用户回到初始登录屏幕ViewController。我真的很难以正确的方式连接这些屏幕。必须说,我对不同类型的 segue 和/或代表没有太多经验,所以在完成一些研究后,我进行了一些试验:

  1. ViewController 上成功登录会触发导航控制器的模态搜索(它本身会导致UserTableViewController
  2. UserTableViewController 有一个注销按钮,可触发另一个模式切换回ViewController。我采用了这些模态序列,因为首先,我不想有一个导致自动创建的后退按钮或类似按钮的层次结构,其次,我不想在这两个屏幕之间有任何“麻烦”,一个有导航控制器,而另一个没有。

...看起来这不是一条路。有些事情在一个循环之后会变得混乱,并且屏幕会以错误的方式改变。我想模态转圈是不可能的,因为至少必须有父母和孩子。下一次试用:

  1. ViewController 上成功登录会触发导航控制器的模态搜索/推送搜索(它本身会导致UserTableViewController
  2. 为了返回登录屏幕,我实现了一个委托而不是另一个 segue,在点击“注销”时触发 - 这里我面临的问题是我无法在 preparingForSegue 中设置 UserTableViewController 的委托在ViewController 上正确。此时,segue.destinationViewController 不能向下转换为 UserTableViewController,而只能转换为 NavigationController,这不允许我在目的地 (UserTableViewController) 设置委托。

第三次试验与第二种方法相同,但从ViewController 直接到UserTableViewController。这可能有效,但现在我的UserTableViewController 上没有任何导航栏...!

当然,我可以在第三种解决方案中进行手动修复,例如插入独立导航栏,但两种方法似乎都没有效率。因此,我非常非常感谢一些提示,突出显示我(完全)在一侧误解的内容,并在另一侧展示了一种很好的方法。非常感谢您的帮助!

编辑: 我可以尝试将导航控制器设置为初始视图控制器,然后让登录屏幕 ViewControllerUserTableViewController 呈现/关闭 - 这是一种实用的方法,还是对于那些登录视图场景有广为人知的最佳实践?

只是视觉帮助:

【问题讨论】:

    标签: swift uinavigationbar ios8 xcode6 downcast


    【解决方案1】:

    请考虑使用“展开”转场。在ViewController创建函数如下:

    @IBAction func unwindToThisViewController(segue: UIStoryboardSegue) {
        yourLogoutCode()
    }
    

    UserTableViewController 中,从“注销”按钮控制并拖动到顶部第三个按钮UserTableViewController 的退出符号,然后选择unwindToThisViewController(或您在ViewController 中选择的任何名称)。

    现在,当您单击注销按钮时,您将返回到ViewController 并执行unwindToThisViewController,您可以在其中放置您的注销代码。

    这是一个例子:

    import UIKit
    
    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    
        func yourLogoutCode() {
            println("Logging Out ...")
        }
    
        @IBAction func unwindToThisViewController(segue: UIStoryboardSegue) {
            self.yourLogoutCode()
        }
    
    
    }
    

    还有 UserTableViewController:

    import UIKit
    var selectedRow = -1
    class UserTableViewController: UITableViewController {
        var firstArray = ["Item1","Item2","Item3","Item4"]
        override func viewDidLoad() {
            super.viewDidLoad()
    
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
    
        }
    
        // MARK: - Table view data source
    
        override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
            return 1
        }
    
        override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return firstArray.count
        }
    
    
        let nameOfCell = "Cell"
        override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCellWithIdentifier(nameOfCell, forIndexPath: indexPath) as UITableViewCell
            cell.textLabel!.text = firstArray[indexPath.row]
            return cell
        }
    
        override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
            selectedRow = indexPath.row
    
        }
    
    
    }
    

    请注意,从 Logout 按钮到 unwind 的整个连接都隐藏在 Storyboard 中。您可以通过查看 Connections Inspector 来确认所有这些正在发生。

    【讨论】:

      【解决方案2】:

      This post 似乎可以准确解决您面临的问题,如果我理解正确的话。

      另外,不是吹毛求疵,而是“模态”,而不是“模态”:)

      【讨论】:

      • 感谢您的意见,我一直在努力!无论如何,我很好奇是否有一种常用的方法来处理登录屏幕,从实际的角度来看,它是初始视图控制器,但它不是导航堆栈的一部分。当一个人注销时它会返回 - 我想知道这个循环中什么样的关系是最好的......此外,我想知道如何在这种情况下实现委托,导航控制器“阻止向下转换” . @尼基
      • 我相信这个导航实际上不应该是这两个控制器中的任何一个的责任,而是一些负责应用程序流的协调器对象。如果您有一个场景需要您在导航控制器的层次结构中将用户注销怎么办?例如,他们的令牌过期了,您需要他们再次登录。
      • 无论如何,首选方法是让呈现控制器知道(通过委托或其他方式)呈现控制器已完成其工作,因此它可以处理解雇。毕竟,在导航中更远的控制器不应该真正知道它在屏幕上的显示方式。
      【解决方案3】:

      我认为这可能是一种可以接受的方式:

      1. 登录视图 (ViewController) 是初始视图控制器
      2. 在成功登录的情况下:从登录视图到处理后续视图的导航控制器的模态切换
      3. 通过实现 UIStoryboardSegue 的子类(需要像这样编写:@objc(DismissSegue) class DismissSegue: UIStoryboardSegue { )在 Swift 中启用dismiss-segues,该子类将其 perform() 覆盖为(sourceViewController.presentingViewController!!).dismissViewControllerAnimated(true, completion: nil)
      4. Dismiss-segue 从后续视图(在我的情况下为 UserTableViewController)返回登录视图
      5. 在允许用户注销的每个视图控制器上实现 prepareForSegue 中的注销操作

      不过,如果有人知道更好的做法,我很高兴听到!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-11-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多