Bahn-X/swift-composable-navigator

Can a screen have itself nested inside?

andrewjmeier opened this issue · 6 comments

Question

[//]: # Is it possible to have a Screen that contains itself in its nesting?

(I'm not sure if this is more of a question or a bug)

Problem description

[//]: # I first observed this behavior when I had a screen (A) that could nest a screen (B) that could then nest the original screen (A) again. The compiler would crash with the error Illegal instruction: 4. I was able to reproduce the issue in the example and it happens if you simply try to nest screen A inside of screen A.

Is there a recommended approach to solve this issue?

struct DetailScreen: Screen {
  let train: Train
  let presentationStyle: ScreenPresentationStyle = .push
  
  struct Builder: NavigationTree {
    var builder: some PathBuilder {
      Screen(
        content: { (screen: DetailScreen) in
          DetailView(train: screen.train)
        },
        nesting: {
          CapacityScreen.Builder()
            DetailScreen.Builder()
        }
      )
    }
  }
}

I forked the example to modify it and show the issue here:
https://github.com/andrewjmeier/swift-composable-navigator/blob/main/Example/Vanilla%20SwiftUI%20Example/Vanilla%20SwiftUI%20Example/DetailView.swift#L16

Hi Andrew 👋

Thank you for this bug report/question. We're aware of this issue, I just forgot to open a GitHub issue for it.

At the moment, navigation paths containing circles are not possible because we do not erase any Content types in the PathBuilders. When you define a NavigationTree declaratively, you can imagine that it builds a single PathBuilder< PageHierarchy >. If the page hierarchy contains any cycles, the PageHierarchy type becomes circular in parts and leads to an infinite type. And therefore, the compiler crashes, because it cannot handle infinite type. 🤯

One way to solve this is to introduce an erased PathBuilder that builds the wrapped PathBuilder and, when this one returns a built content, erases it to AnyView.

I will look into this soon, but if you want to give it a go, feel free to do so. :)

Have a great day! 🙌

Thanks!

I'll play around it a bit, but this is pretty far over my head in terms of my familiarity with Swift so I doubt I'll make much progress.

No worries, I'll get to it some time this week and keep you updated on this issue.

Awesome! Thanks for such a quick turn around. Let me know if there's anything I can do to help out

@andrewjmeier

Just released v0.2.0 that allows erasing circular paths, that should fix your issue. Enjoy! :)

@ohitsdaniel this is awesome!! Thanks for such a quick turnaround 😃