Closed IgorRatynski closed 1 year ago
@IgorRatynski Hi
The problem is in swift types limitation here. You cant just use any ContainerAction
there. Any
implies completely any container actions while the assembly relies on its type to understand what type of the ContainerViewControllers are allowed. There are examples in the Example app how to write that. The easiest way if you dont know is to do that if on the top level and return 2 differnt chain the way you are already doing it. Have a look at the SwitchAssembly.
I am typing from my phone. When Ill have the access to my laptop ill try to provide you better answer.
I tried it, but it didn't work. I must have done something wrong. Okay, thanks for the quick reply!
@IgorRatynski Technically there is nothing wrong in returning 2 separate chains. The route composer is not rewritten to support new swift type erasure features yet. I tried it when they released that feature bot started to hit Segmentation fault
at some point due to compiler issues. Probably in the future it can be possible. But Ill have a look if it can be simplified.
@IgorRatynski Thinking about it SwitchAssembly
wont help you. If you want to simplify that you'll need to write a custom container action that would do either of actions depending on the result of the view controller presence. It will be even safer as your ClassWithContextFinder<ClientManagerChatViewController, Context>
finder searches everywhere and not necessary at the UINavigationController that it going to push to. You still can use ClassWithContextFinder
inside, just use the navigationController action receives as its starting point with option containing
@IgorRatynski Technically there is nothing wrong in returning 2 separate chains. The route composer is not rewritten to support new swift type erasure features yet. I tried it when they released that feature bot started to hit
Segmentation error
at some point due to compiler issues. Probably in the future it can be possible. But Ill have a look if it can be simplified.
@ekazaev As far as I'm concerned, it's not a good approach to code when I'm rewriting about 15 lines because of one line, if I can avoid doing that. If not, then yeah, nothing wrong with that : )
@IgorRatynski Something like:
public struct PushReplacingLastIfNeededAction<ViewController: UINavigationController>: ContainerAction {
private let comparisonBlock: (UIViewController, UIViewController) -> Bool
public init(comparing comparisonBlock: @escaping (UIViewController, UIViewController) -> Bool) {
self.comparisonBlock = comparisonBlock
}
public func perform(embedding viewController: UIViewController,
in childViewControllers: inout [UIViewController]) {
if let lastViewController = childViewControllers.last,
comparisonBlock(lastViewController, viewController) {
childViewControllers.removeLast()
}
childViewControllers.append(viewController)
}
public func perform(with viewController: UIViewController,
on navigationController: ViewController,
animated: Bool,
completion: @escaping (_: RoutingResult) -> Void) {
var viewControllers = navigationController.viewControllers
perform(embedding: viewController, in: &viewControllers)
navigationController.setViewControllers(viewControllers, animated: animated)
if let transitionCoordinator = navigationController.transitionCoordinator, animated {
transitionCoordinator.animate(alongsideTransition: nil) { _ in
completion(.success)
}
} else {
completion(.success)
}
}
}
//...
.using(PushReplacingLastIfNeededAction<UINavigationController>(comparing: { lastViewController, newViewController in
return /* Cast view controllers, compare and return true if last one needs to go */
}))
//...
As far as I'm concerned, it's not a good approach to code when I'm rewriting about 15 lines because of one line, if I can avoid doing that. If not, then yeah, nothing wrong with that : )
@IgorRatynski I dont want to fall into philosophy but as far as I remember R.Martin says something like: If the library in the project gives you too much or too little functionality, or conflicts with the expected functionality it consequently makes code dirtier. You can avoid this by simply applying patterns like Decorator, Adapter, Facade or others above this library/libraries.
In your case StepAssembly sits in the function like func goToChat(with context: WhateverContext)
so the Facade pattern is already used. So if nobody digs there - it is fine :). But the solution with the custom action is better for sure.
Best of luck.
Thank you very much, @ekazaev, for your help with the problem and the library. Great job!
My pleasure. Best of luck.
I'm trying to implement a transition type depending on the presence of a specific UIViewController with a certain context.
NavigationController it's child of UINavigationController As a result, I'm returning the entire Destination construction through an if-else statement instead of just selecting the type of navigation action. Could you possibly help me find a better way to solve this?