【问题标题】:How do I stop a view from refreshing each time I return from a detail view in SwiftUI?每次从 SwiftUI 中的详细视图返回时,如何阻止视图刷新?
【发布时间】:2020-08-20 14:51:36
【问题描述】:

我有一个显示帖子列表的视图。我已经实现了infinite scrolling,它运行正常。但是,我遇到了一个小问题,并且试图解决它让我陷入困境。

主视图

struct PostsHomeView: View {

    @EnvironmentObject var viewModel: ViewModel
    @State var dataInitiallyFetched = false

    var body: some View {
    
        NavigationView {
        
             VStack(alignment: .center, spacing: 0) {

                 if self.viewModel.posts.count > 0  {
                         
                     PostsListView(posts: self.viewModel.posts,
                                  isLoading: self.viewModel.canFetchMorePosts,
                                  onScrolledAtBottom: self.viewModel.fetchMorePosts
                     )

                 } else {

                     VStack {
                         
                         Text("You have no posts!")
                         
                     }
                 }
             }
             .onAppear() {

                 if !self.dataInitiallyFetched {

                     self.viewModel.fetchMostRecentPosts()

                     self.dataInitiallyFetched = true
                 }
             }
             .navigationBarTitle("Posts", displayMode: .inline)
       }
    }
}

列表视图

struct PostsListView: View {
    
    @EnvironmentObject var viewModel: ViewModel      
    let posts: [Post]
    let isLoading: Bool
    let onScrolledAtBottom: () -> Void

    var body: some View {
       List {

           postsList
           
           if isLoading {
               loadingIndicator
           }
       }
    }
       
    private var postsList: some View {
               
       ForEach(posts, id: \.self) { post in

           PostsCellView(post: post)
               .onAppear {
                         
                   if self.posts.last == post {

                           self.onScrolledAtBottom()
                   }
               }
       }
       .id(UUID())
    } 
}

问题

点击列表中的一个帖子后,我会进入详细视图。当我点击导航栏的后退按钮以返回帖子列表时,整个视图被重新加载并且我的帖子获取方法再次被触发。

为了阻止获取最新帖子的 fetch 方法触发,我添加了一个标志,在初始加载后将其设置为 true。当我在详细信息视图和帖子主屏幕之间来回切换时,这会阻止获取初始帖子集的 fetch 方法触发。

我已经尝试了各种方法来阻止 fetchMorePosts 函数触发,但我一直在绕圈子。我在视图模型中的 fetchMorePosts 函数顶部添加了一个保护语句。它检查字符串是否等于“homeview”,如果不等于,则未完成提取。每当访问详细视图时,我都会将此字符串设置为“detailview”,然后在保护语句中将其重置为“homeview”。

guard self.lastView == "homeview" else {
    self.lastView = "homeview"
    return
}

这在一定程度上有效,但我不断发现它无法按预期工作的情况。必须有一种直接的方式来告诉 SwiftUI 不要重新加载视图。问题是该方法位于onAppear 闭包中,这对于无限滚动的工作至关重要。我还没有使用 iOS 14,所以我不能使用@StateObject。

有没有办法告诉 SwiftUI 在我每次从详细视图返回时不要触发 onAppear

提前致谢

【问题讨论】:

  • 它被重建是因为你明确地用.id(UUID())强制它重建。您会准备带有问题演示的独立可测试示例吗?否则很难有人猜到解决方案。
  • @Asperi 嗨,谢谢。这解决了这个问题。我添加了.id(UUID()),因为我读到它可以提高性能。我没有提供可测试示例的原因是因为我的项目非常复杂,并且我提供的代码确实被精简了,所以我确信我的可测试示例与实际项目会有很大差异。

标签: ios swift swiftui swiftui-list swiftui-navigationlink


【解决方案1】:

罪魁祸首是.id(UUID())。我把它从我的列表中删除了,一切都恢复了。

感谢阿斯佩里。非常感谢您的帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-11
    • 1970-01-01
    • 2020-11-20
    相关资源
    最近更新 更多