使用UINavigationController进行prepareForSegue切换...更好的方法?

时间:2018-05-24 09:38:58

标签: swift uinavigationcontroller switch-statement segue

我有几个segues呈现模态视图控制器。

class ProfileViewController: UIViewController {
    func configure(profile: Profile) { 
        // Some ProfileViewController specific config
    }
}

class SettingsViewController: UIViewController {
   func configure(settings: Settings) { 
        // Some SettingsViewController specific config
    }
}

所以这里有一些非常标准的代码,我们都写过很多次......

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    switch segue.destination {
    case let nav as UINavigationController:
        switch nav.topViewController {
        case let pvc as ProfileViewController:

            pvc.configure(profile: profile)
        case let svc as SettingsViewController:

            svc.configure(settings: settings)
        default:
            break
        }
    default:
        break
    }
}

我也是这样试过的......

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    switch segue.destination {
    case let nav as UINavigationController
        where nav.topViewController is ProfileViewController:

        (nav.topViewController as! ProfileViewController).configure(profile: profile)
    case let nav as UINavigationController
        where nav.topViewController is SettingsViewController:

        (nav.topViewController as! SettingsViewController).configure(settings: settings)
    default:
        break
    }
}

但我想做的是两者结合......

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    switch segue.destination {
    case let nav as UINavigationController
        where let pvc = nav.topViewController as ProfileViewController:

        pvc.configure(profile: profile)
    case let nav as UINavigationController
        where let svc = nav.topViewController as SettingsViewController:

        svc.configure(settings: settings)
    default:
        break
    }
}

但显然不会编译。有人遇到过更好的模式吗?

更新

扩展@ Serj的答案......

extension UIStoryboardSegue {
    var destinationNavTopViewController: UIViewController? {
        return (destination as? UINavigationController)?.topViewController
    }
}

然后

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    switch (segue.destination, destinationNavTopViewController) {
    case let (_, pvc as ProfileViewController):

        pvc.configure(profile: profile)
    case let (_, svc as SettingsViewController):

        svc.configure(settings: settings)
    case let (ovc as OtherViewController, _):
        ovc.configure…
    default:
        break
    }
}

1 个答案:

答案 0 :(得分:2)

在问这个问题时,我们可以考虑两种情况:

  1. 您想要实现的具体用例
  2. switch语句
  3. 的更一般用例

    现在针对特定用例,您似乎只想在有导航控制器时切换segue.destination。您可以使用if letguard let轻松实现此目标,如下所示:

    guard let navigationController = segue.destination as? UINavigationController else { return }
    guard let topController = navigationController.topViewController else { return }
    switch topController {
      case let profileViewController as ProfileViewController:
        print("Do something for profile view controller")
      default:
        break
    }
    

    现在第二种情况更为通用,关于如何在switch语句中提供这两个变量。答案是元组。例如,我将提供Apple文档中的示例,然后为您的特定用例提供示例。

    let anotherPoint = (2, 0)
    switch anotherPoint {
    case (let x, 0):
        print("on the x-axis with an x value of \(x)")
    case (0, let y):
        print("on the y-axis with a y value of \(y)")
    case let (x, y):
        print("somewhere else at (\(x), \(y))")
    }
    

    现在有关如何使用您的用例实现上述内容的示例,请注意它可以改进一个丑陋的示例,但要明白:

    switch (segue.destination, (segue.destination as? UINavigationController)?.topViewController) {
    case (let nav as UINavigationController, let viewController as ProfileViewController):
        return
    // Maybe the destination wasn't a nav maybe it was the sign in view controller and you don't care about the second variable
    case (let signInController as SignInViewController, let _):
        return
    default:
        return
    }
    

    这是切换语句能够轻松切换元组的强大功能。我希望我的例子能回答你的问题。我尝试用所有含糊之处覆盖问题的所有部分。