Closed iRiziya closed 2 years ago
Hello!
You can pass a path binding to ForgetPasswordView
by defining
@Binding var path: PathPresenter.Path
in ForgetPasswordView
.
Then, you can pass path during initialisation of ForgetPasswordView
:
path.append(ForgetPasswordView(path: $path),
type: .animated(transition: .move(edge: .leading), animation: .easeIn))
Now you can use path in ForgetPasswordView
as usual
Also, architecture-wise, I would suggest not to pass path all around the app.
It may be fine in small examples like yours, but on a large scale, if views will push and pop uncontrollably, it will be a mess
Thanks for the quick response. @AlexRoar
I already tried @Binding
but its not working as expected. And also my app is large so what would be best approach in that case?
Alright @Binding
worked this time because I removed the embedded PathPresenter
from ForgetPasswordView
. But I am worrying about infinite navigation chain If I will have to navigate through so many screens.
I already tried @Binding but its not working as expected. And also my app is large so what would be best approach in that case?
Complete working example:
import SwiftUI
import PathPresenter
struct ContentView: View {
@State var path = PathPresenter.Path()
var body: some View {
PathPresenter.RoutingView(path: $path){
VStack {
Spacer()
Button("Forgot password") {
path.append(
ForgotPasswordView(path: $path),
type: .animated(
transition: .scale,
animation: .easeIn)
)
}
Spacer()
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
.border(.blue)
}
}
struct ForgotPasswordView: View {
@Binding var path: PathPresenter.Path
var body: some View {
VStack(alignment: .center){
Spacer()
VStack {
Text("Restore password screen")
Button("back") {
path.removeLast()
}
}
.background(.white)
Spacer()
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Alright
@Binding
worked this time because I removed the embeddedPathPresenter
fromForgetPasswordView
. But I am worrying about infinite navigation chain If I will have to navigate through so many screens.
You need to somehow restrict subviews to be able to do limited actions with path. In your example you do not need to pass the whole path to the subview. You can pass some closure like backAction: () -> ()
that will be called when user presses back button.
And inside this closure you will do needed actions with path.
Also, check out MVVM-C architecture. I believe it's a nice extension of MVVM that has good control over navigation.
Also, I'm planning to extend this library with wrapper around path that will restrict views from doing some mess with all other views ;)
Alright got it. Thanks.
Can you make it global? so we can use it on every page as an EnvironmentObject
.
I am using a similar library for SwiftUI navigation but its not working for macOS
because of missing NavigationView
Can you make it global? so we can use it on every page as an EnvironmentObject.
You can make a class wrapper and pass it as EnvironmentObject
class PathObserved: ObservableObject {
@Published var path = PathPresenter.Path()
}
But if you need this object in global space, it's a smell of bad code architecture. This library was specifically designed without EnvironmentObjects
and ObservableObject
.
Ah ok. It's hard to deal with Navigation in macOS so I'll have to go for any of this. Can the given class wrapper create a mess for large app having many pages?
Can the given class wrapper create a mess for large app having many pages?
The biggest concern I have is such situation:
Result: view B removed unexpectedly, and view A is not not removed. So, yes. Uncontrollable pushing/popping of views will hurt your app.
I will try to address such issue in future releases, creating new structure for managing such situations.
Ok thanks
I am following the given example but it is still unclear that how can I use the same
path
variable in child view. The main path variable should be accessible to all its child view and must be binded.I have
LoginView
andForgetPasswordView
. I have declaredpath
as below inLoginView
@State var path = PathPresenter.Path()
and embedded login layout inside PathPresenter like this
and then I am appending
ForgetPasswordView
in this pathbut now the
back button
is inside theForgetPasswordView
so I am wondering how can I use the same path variable to go back or to append any new View?