如何创建匹配任意枚举关联值的NavigationLink?
用户定义了以下导航枚举:
enum NavRoute { case loggedOut case onboarding(OnboardingRoute) enum OnboardingRoute { case page1 case page2 } } @State var route = NavRoute.onboarding(.page1)
希望编写如下NavigationLink,让tag参数匹配任意OnboardingRoute类型的关联值:
NavigationLink( tag: NavRoute.onboarding(any), // 这里应该填什么? selection: $route ) { OnboardingView() } label: { Text("Create account") }
解决方案
Swift中NavigationLink的selection和tag匹配依赖精确的Equatable判断,默认情况下不同关联值的onboarding case会被视为不相等。要实现“匹配任意OnboardingRoute关联值”的需求,有两种常用方法:
方法1:自定义Equatable实现
让NavRoute遵循Equatable,并改写相等判断逻辑,只要两个case都是onboarding类型,就视为相等:
enum NavRoute: Equatable { case loggedOut case onboarding(OnboardingRoute) enum OnboardingRoute: Equatable { case page1 case page2 } static func == (lhs: NavRoute, rhs: NavRoute) -> Bool { switch (lhs, rhs) { case (.loggedOut, .loggedOut): return true case (.onboarding, .onboarding): // 忽略关联值,所有onboarding case视为相等 return true default: return false } } }
之后NavigationLink的tag可以填任意一个onboarding实例(比如.onboarding(.page1)),只要route是任意onboarding关联值,就会匹配成功:
NavigationLink( tag: NavRoute.onboarding(.page1), selection: $route ) { OnboardingView() } label: { Text("Create account") }
方法2:使用isActive绑定替代selection
如果不想修改枚举的Equatable逻辑,可以通过计算属性判断当前路由是否属于onboarding类型,用isActive绑定来控制NavigationLink:
@State var route = NavRoute.onboarding(.page1) // 自定义绑定,判断当前是否处于onboarding路由 private var isOnboardingActive: Binding<Bool> { Binding( get: { if case .onboarding = route { return true } return false }, set: { isActive in if !isActive { // 退出onboarding时切换到指定路由,比如loggedOut route = .loggedOut } } ) } // 使用isActive的NavigationLink NavigationLink( isActive: isOnboardingActive ) { OnboardingView() } label: { Text("Create account") }
内容的提问来源于stack exchange,提问作者joshuakcockrell
相关产品推荐
相关产品推荐

