代码之家  ›  专栏  ›  技术社区  ›  Ashley Mills

用uinavigationcontroller__准备Segue交换机更好的方法?

  •  2
  • Ashley Mills  · 技术社区  · 7 年前

    我有几段介绍模态视图控制器。

    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 回复  |  直到 7 年前
        1
  •  2
  •   Serj    7 年前

    当问到如何考虑两种情况时:

    1. 关于您想要实现什么的特定用例
    2. 更通用的用例 switch 声明

    现在对于特定的用例,您似乎只希望在打开 segue.destination 当你有导航控制器的时候。你可以用一个 if let guard 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语句中同时使用这两个变量。答案是元组。例如,我将提供一个来自苹果文档的示例,然后为您的特定用例提供一个示例。

    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
    }
    

    这就是switch语句能够如此轻松地切换元组的能力。我希望我的例子能回答你的问题。我试图用所有含糊不清的词句来涵盖问题的所有部分。