Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
356 views
in Technique[技术] by (71.8m points)

ios - SwiftUI, how to switch to a view without recreating it?

I have a few different views in my application that the user can switch between. One of these views is a SearchView that I have created. This view can be used to search for a user specified string in a document and to then select one of the search results to jump to. This is implemented by generating a bunch of search results when the user presses the search button. Each search result is a composition of other views and this causes the search process and search result generation process to take quite a long time, this is fine when it just happens initially. My problem is that if the user does a search in the search view, switches to another view, and then goes back to the search view, it takes a long time to recreate all of the search result views.

How can I save the search view or search result views in some variable that doesn't get cleared to allow reuse of the already previously generated search view results?

I already use an environment object to store the data used to create the search results, such as the search string, sample text, chapter, etc. So that data isn't recreated when switching back to the search view, the only problem is the view itself.

This is the search view struct:

@EnvironmentObject var modelView: ModelView

var OnJumpToSearchResult: ((Int) -> Void)?

var body: some View {
    ScrollView {
        HStack {
            //Search Field
            HStack {
                TextField("Search string here", text: $modelView.searchString)
            }
            .padding()
            .background(Color(.systemGray5))
            .cornerRadius(6)
            .padding(.horizontal)
            
            //Search Button
            Button(action: { modelView.searchResults = PerformSearch(pages: modelView.searchPages, pageHeadings: modelView.pageHeadings, searchString: modelView.searchString, sampleRadius: sampleRadius) }, label: {
                Text("Search")
                    .padding(.trailing)
            })
        }
        
        //Display Search Results
        if modelView.searchResults.isEmpty {
            EmptyView()
        }
        else
        {
            ForEach(modelView.searchResults, id: .self) { searchResult in
                Button(action: {
                    if OnJumpToSearchResult != nil {
                        OnJumpToSearchResult?(searchResult.pageNumber - 1) }
                    
                }) {
                    VStack {
                        Text("(searchResult.heading)")
                            .bold()
                        HStack {
                            HighlightedTextView(String(searchResult.sampleText), matching: modelView.searchString, caseInsensitive: true)
                            Spacer()
                            Text("s.(searchResult.pageNumber)")
                        }
                        .padding()
                    }
                    
                    
                    Divider()
                        .background(Color(.systemGray4))
                        .padding(.leading)
                }
            }
        }
    }
}

The parent view of search view initializes a search view on initialization and reuses it (instead of reinitializing a new one) whenever it gets updated.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

If your search view doesn't depend on anything from its parent then you can simply create it once in the parent view and it won't be re created when the parent view relays out its subviews (but will be recreated if the parent view is recreated)

struct ViewThatRendersSearchView: View {
  let searchView = SearchView() // create it one time
  @State private var shouldShowSearchView = false
  var body: some View {
    if shouldShowSearchView {
      searchView // Won't be recreated each time
    } else {
      EmptyView()
    }
  }
}


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
...