-
Notifications
You must be signed in to change notification settings - Fork 25
PathBuilder
PathBuilders define how a navigation path is built into a view hierarchy
public protocol PathBuilder
Performs an action before this PathBuilder
is built.
func beforeBuild(perform action: @escaping () -> Void) -> _PathBuilder<Content>
Erases circular navigation paths
public func eraseCircularNavigationPath() -> AnyPathBuilder
NavigationTrees define a PathBuilder<Content: View>
via their builder computed variable.
The Screen
PathBuilder adds NavigationNode<ScreenView, Successor>
s to the NavigationTree.
One the one hand, this makes sure that all valid navigation paths are known at build time. On the other hand, this leads to problems if the NavigationTree contains a circular path.
The following NavigationTree leads to a circular path:
struct HomeScreen {
let presentationStyle = ScreenPresentationStyle.push
struct Builder: NavigationTree {
var builder: _PathBuilder<
NavigationNode<HomeView,
NavigationNode<HomeView, ...> // <- Circular Type
>
> {
Screen(
HomeScreen.self,
content: HomeView.init,
nesting: {
HomeScreen.Builder()
}
)
}
}
}
Whenever a Screen
Builder is contained multiple times in a navigation tree,
the Screen
and its successors are contained recursively in the NavigationTrees content type.
Unfortunately, the compiler is not able to resolve recursive, generic types. To solve this, we can erase PathBuilders that lead to circular paths.
struct HomeScreen {
let presentationStyle = ScreenPresentationStyle.push
struct Builder: NavigationTree {
var builder: _PathBuilder<
NavigationNode<HomeView, AnyView> // <- No longer circular
> {
Screen(
HomeScreen.self,
content: HomeView.init,
nesting: {
HomeScreen
.Builder()
.eraseCircularNavigationPath()
}
)
}
}
}
onDismiss
allows to perform an action whenever the AnyScreen
object built by the wrapped PathBuilder
changes
func onDismiss(
perform: @escaping (AnyScreen) -> Void
) -> _PathBuilder<OnDismissView<Content>>
onDismiss
keeps track of the last built AnyScreen
and performs the defined action whenever a screen is no longer built.
If your PathBuilder
is wrapped in a conditional path builder, make sure to attach onDismiss
to the outer-most conditional PathBuilder
.
PathBuilders.anyOf(
DetailScreen.Builder(),
SettingsScreen.Builder()
)
.onDismiss { (screen: AnyScreen) in
print("Dismissed \(screen)")
}
- perform: Block to perform when the wrapped
PathBuilder
builds a newAnyScreen
object. Called with the previously builtAnyScreen
instance.
onDismiss
allows to perform an action whenever aScreen
is dismissed
func onDismiss<Dismissed: Screen>(
perform: @escaping (Dismissed) -> Void
) -> _PathBuilder<OnDismissView<Content>>
onDismiss
keeps track of the last built Screen
and performs the defined action whenever a screen is no longer built.
PathBuilders.if(
screen: { (screen: DetailScreen) in
PathBuilders.screen(
DetailScreen.self,
content: {
DetailView(mainStore.detailStore)
},
nesting: SettingsScreen.Builder().onDismiss(of: SettingsScreen.self) {
// only called if DetailScreen is contained in the current navigation path
print("Dismissed settings screen")
}
)
.beforeBuild {
mainStore.selectedDetail = screen.detailID
}
}
)
.onDismiss { (screen: DetailScreen) in
mainStore.selectedDetail = nil
}
- perform: Block to perform when the wrapped
PathBuilder
no longer builds the definedDismissed: Screen
type. Called with the previously builtDismissed
instance.
onDismiss
allows to perform an action whenever aScreen
is dismissed
func onDismiss<Dismissed: Screen>(
of: Dismissed.Type,
perform: @escaping () -> Void
) -> _PathBuilder<OnDismissView<Content>>
onDismiss
keeps track of the last built Screen
and performs the defined action whenever a screen is no longer built.
PathBuilders.if(
screen: { (screen: DetailScreen) in
PathBuilders.screen(
DetailScreen.self,
content: {
DetailView(mainStore.detailStore)
},
nesting: SettingsScreen.Builder.onDismiss(of: SettingsScreen.self) {
// only called if DetailScreen is contained in the current navigation path
print("Dismissed settings screen")
}
)
.beforeBuild {
mainStore.selectedDetail = screen.detailID
}
}
)
.onDismiss(of: DetailScreen.self) {
mainStore.selectedDetail = nil
}
- of: defines the
Dismissed: Screen
type - perform: Block to perform when the wrapped
PathBuilder
no longer builds the definedDismissed: Screen
type.
public func build<S: Screen>(pathElement: S) -> Content?
onDismiss
allows to perform an action whenever the AnyScreen
object built by the wrapped PathBuilder
changes
public func onDismiss<State: Equatable, Action: Equatable>(
send action: @escaping (AnyScreen) -> Action,
into store: Store<State, Action>
) -> _PathBuilder<OnDismissView<Content>>
onDismiss
keeps track of the last built AnyScreen
and performs the defined action whenever a screen is no longer built.
If your PathBuilder
is wrapped in a conditional path builder, make sure to attach onDismiss
to the outer-most conditional PathBuilder
.
PathBuilders.anyOf(
DetailScreen.Builder,
SettingsScreen.Builder
)
.onDismiss(
send: { screen in MainAction.dismissedScreen(screen) },
into: mainStore
)
- action: Action sent on dismiss.
- store: Store the action is sent into.
onDismiss
allows to perform an action whenever aScreen
is dismissed
public func onDismiss<Dismissed: Screen, State: Equatable, Action: Equatable>(
send action: @escaping (Dismissed) -> Action,
into store: Store<State, Action>
) -> _PathBuilder<OnDismissView<Content>>
onDismiss
keeps track of the last built Screen
and performs the defined action whenever a screen is no longer built.
PathBuilders.if(
screen: { (screen: DetailScreen) in
PathBuilders.screen(
DetailScreen.self,
content: {
DetailView(mainStore.detailStore)
},
nesting: SettingsScreen.Builder().onDismiss(of: SettingsScreen.self) {
// only called if DetailScreen is contained in the current navigation path
print("Dismissed settings screen")
}
)
.beforeBuild {
mainStore.selectedDetail = screen.detailID
}
}
)
.onDismiss(
send: { (screen: DetailScreen) in MainAction.dismissDetail(id: screen.id) },
into: mainStore
)
- action: Action sent on dismiss.
- store: Store the action is sent into.
onDismiss
allows to perform an action whenever aScreen
is dismissed
public func onDismiss<Dismissed: Screen, State: Equatable, Action: Equatable>(
of screen: Dismissed.Type,
send action: Action,
into store: Store<State, Action>
) -> _PathBuilder<OnDismissView<Content>>
onDismiss
keeps track of the last built Screen
and performs the defined action whenever a screen is no longer built.
PathBuilders.if(
screen: { (screen: DetailScreen) in
PathBuilders.screen(
DetailScreen.self,
content: {
DetailView(mainStore.detailStore)
},
nesting: SettingsScreen.Builder().onDismiss(of: SettingsScreen.self) {
// only called if DetailScreen is contained in the current navigation path
print("Dismissed settings screen")
}
)
.beforeBuild {
mainStore.selectedDetail = screen.detailID
}
}
)
.onDismiss(
of: DetailScreen.self,
send: MainAction.dismissDetail,
into: mainStore
)
- of: defines the
Dismissed: Screen
type. - action: Action sent on dismiss.
- store: Store the action is sent into.
associatedtype Content: View
func build(pathElement: AnyScreen) -> Content?
Generated at 2021-04-29T07:59:04+0000 using swift-doc 1.0.0-beta.6.
Types
- AnyPathBuilder
- AnyScreen
- Deeplink
- DeeplinkComponent
- DeeplinkComponent.Argument
- DeeplinkHandler
- DeeplinkParser
- EitherAB
- EitherABC
- EitherABCD
- EitherABCDE
- EitherABCDEF
- EitherABCDEFG
- EitherABCDEFGH
- EitherABCDEFGHI
- EitherABCDEFGHIJ
- IdentifiedScreen
- NavigationNode
- NavigationTreeBuilder
- Navigator
- Navigator.Datasource
- Navigator.DidAppearInvocation
- Navigator.DismissInvocation
- Navigator.GoBackToInvocation
- Navigator.GoToInvocation
- Navigator.GoToPathInvocation
- Navigator.NavigationIdentifier
- Navigator.ReplaceContentInvocation
- Navigator.ReplacePathInvocation
- Navigator.ReplaceScreenInvocation
- NavigatorKey
- OnDismissView
- PathBuilders
- PathBuilders.EmptyBuilder
- PathBuilders.WildcardView
- PathComponentUpdate
- PathUpdate
- Root
- ScreenPresentationStyle
- TreatSheetDismissAsAppearInPresenterKey
- _PathBuilder