When I use the "next article" button to jump to the article details page with index 3, I want to go directly back to the article list page instead of the article details page with index 2.I tried to search for methods to return to the specified page and destroy the page, but I didn't find them.How to achieve this effect in swiftui?Thanks.I guess the same scenario will happen in other mobile development, right? The ArticleListView is :
struct ArticleListView: View {
@EnvironmentObject var modelData:ModelData
var body: some View {
NavigationView{
List{
ForEach(modelData.articleList){ article in
NavigationLink(destination:ArticleDetail(index:article.index)){
ArticleItem(index:article.index);
}
}
}
.listStyle(PlainListStyle())
}
}
}
The ArticleDetail is like this:
struct ArticleDetail: View {
@EnvironmentObject var modelData:ModelData
var index:Int
var body: some View {
VStack{
Text(modelData.articleList[index].htmlText)
NavigationLink(destination:ArticleDetail(index:self.index+1)){
Text("next article")
}
}
}
}
The Article/ArticleItemView/ModelData is like this:
struct Article:Identifiable{
var id = UUID()
var index:Int
var htmlText:String
}
struct ArticleItem: View {
@EnvironmentObject var modelData:ModelData
var index:Int
var body: some View {
Text(modelData.articleList[index].htmlText)
}
}
final class ModelData:ObservableObject {
@Published var articleList = [Article(index:0,htmlText: "first test text "),Article(index:1,htmlText: "second test text"),Article(index:2,htmlText: "third test text")]
}
This solution has some potential scalability issues, but it gets the basic job done:
struct Article {
var id = UUID()
}
struct ContentView: View {
var articles = [Article(), Article(), Article(), Article()]
@State private var activeId : UUID?
func activeBinding(id: UUID) -> Binding<Bool> {
.init { () -> Bool in
activeId == id
} set: { (newValue) in
activeId = newValue ? id : nil
}
}
var body: some View {
NavigationView {
VStack(alignment: .leading, spacing: 20) {
ForEach(articles, id: \.id) { article in
NavigationLink(destination: ArticleView(article: article,
articles: articles,
popToTop: { activeId = nil }),
isActive: activeBinding(id: article.id)) {
Text("Link to article: \(article.id)")
}
}
}
}
}
}
struct ArticleView : View {
var article : Article
var articles : [Article]
var popToTop: () -> Void
var body : some View {
VStack(alignment: .leading, spacing: 20) {
Text("Current: \(article.id)")
Button("Pop") {
popToTop()
}
ForEach(articles, id: \.id) { listArticle in
NavigationLink(destination: ArticleView(article: article, articles: articles, popToTop: popToTop)) {
Text("Link to article: \(listArticle.id)")
}
}
}
}
}
On the main page, the top-level article ID is stored in a @State
variable. That is tied with a custom binding to an isActive
property on the top-level link. Basically, when the article is active, the link is presented and when activeId
is nil, the link becomes inactive, and pops to the top.
Because that's the top level view, any views lower in the stack will get popped off if that top-level NavigationLink
is inactive.
popToTop
is a function that gets passed down to the subsequent article views and gets called if the "Pop" button is pressed.