簡體   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