繁体   English   中英

SwiftUI 从列表中删除项目时奇怪的列表行为

[英]SwiftUI weird List behavior when removing item from list

我的列表一直有问题,在删除项目后,它会被正确删除,但如果我在同一视图的两个分支之间切换,我的列表项目会得到这个奇怪的前导填充。

不确定如何准确解释它,所以我附上了发生的事情。

https://imgur.com/CbzCSiQ

这是我的列表行代码:

if (/** condition **/) {
    EmptyView()
} else {
    ZStack(alignment: .center) {
        NavigationLink(
            destination: MovieDetailsView(movie: moviesVM.movie)) {
                EmptyView()
            }.opacity(0)
        WebImage(url: moviesVM.movie.backdropUrl)
            .resizable()
            .placeholder {
                Image("tile_placeholder")
                    .resizable()
                    .aspectRatio(aspectRatioW780Poster, contentMode: .fill)
                    .frame(maxHeight: 170)
                    .clipped()
            }
            .transition(.fade(duration: 0.5))
            .aspectRatio(aspectRatioW780Poster, contentMode: .fill)
            .frame(maxHeight: 170)
            .clipped()
            .overlay(TextOverlay(movieOrShow: moviesVM.movie))
    }
    .swipeActions(edge: .trailing, allowsFullSwipe: false) {
        // buttons that invoke removal
    }
}

列表行在“配置文件”视图中实例化,如下所示:

NavigationView {
    VStack {
        if profileVM.profileRepository.profile == nil {
            HStack(alignment: .center) {
                Text("Please log in or sign up to use your watchlist. ☺️")
            }
        }
        
        if profileVM.profileRepository.profile != nil {
            HStack {
                Text("Watched")
                Toggle("Watched", isOn: $profileVM.defaultTab)
                    .onChange(of: profileVM.defaultTab, perform: { _ in
                        profileVM.updateDefaultTab()
                    })
                    .labelsHidden()
                    .tint(Constants.MUSH_BLUE)
                Text("Watchlist")
            }

            // this is where my view "branches" depending on the toggle
            HStack {
                if !profileVM.defaultTab {
                    ZStack(alignment: .center) {
                        List {
                            ForEach(Array(profileVM.profileRepository.watchedMovies), id: \.id) { movie in
                                MovieListRow(moviesVM: MoviesViewModel(profileRepository: profileVM.profileRepository, movie: movie, fromProfile: true))
                                    .id(movie.id)
                                    .listRowInsets(EdgeInsets())
                                    .listRowSeparator(.hidden)
                            }
                        }
                        .listStyle(InsetListStyle())
                        if profileVM.profileRepository.watchedMovies.count == 0 {
                            Text("Nothing here yet :)")
                        }
                    }
                } else {
                    ZStack(alignment: .center) {
                        List {
                            ForEach(Array(profileVM.profileRepository.watchlistedMovies), id: \.id) { movie in
                                MovieListRow(moviesVM: MoviesViewModel(profileRepository: profileVM.profileRepository, movie: movie, fromProfile: true))
                                    .id(movie.id)
                                    .listRowInsets(EdgeInsets())
                                    .listRowSeparator(.hidden)
                            }
                        }
                        .listStyle(InsetListStyle())
                        if profileVM.profileRepository.watchlistedMovies.count == 0 {
                            Text("Nothing here yet :)")
                        }
                    }
                }
            }
        }
    }
    .navigationTitle("Watchlist")
}

调试视图层次结构

调试视图

这里有一些想法:

  1. moviesVM - 我们不在 SwiftUI 中使用视图 model 对象。对于瞬态视图数据,我们使用带有@State@Binding的视图结构,这使得结构值类型实际上表现得像 object,因为当结构再次初始化时,它会自动具有与上次初始化时相同的属性值。 我们确实使用 object 来管理我们的 model 数据结构或 arrays 的生命周期,在我们使用environmentObject传递给视图的ObservableObject@Published属性中。
  2. ForEach(Array( - ForEach View 需要提供您的 model 数据才能正常工作,这通常是一个符合Identifiable的结构数组。例如ForEach($model.movies) $movie in我们想要写入访问权限时。
  3. MovieListRow(moviesVM MoviesViewModel( - 像这样在body中初始化对象是错误的,这会减慢 SwiftUI 并导致 memory 泄漏。在 body 中,我们只初始化超快速值类型的视图数据结构。body func 被反复调用,之后SwiftUI 已经区分并更新了屏幕上的标签等所有这些视图结构都被丢弃了。
  4. 你的body太大了,我们应该用少量的let@State将它分解成小的视图。 这称为严格失效。 原因是 SwiftUI 具有依赖性和更改跟踪功能,如果正文太大,则效率不高。 命名结构可能会很棘手,因为它们是基于数据而不是屏幕区域,从ContentView1ContentView2等开始,直到您找到一个好的命名方案,例如一些基于属性的命名视图。

推荐观看SwiftUI中的WWDC 2020 Data Essentials,学习正确使用SwiftUI。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM