[英]SwiftUI weird List behavior when removing item from list
我的列表一直有問題,在刪除項目后,它會被正確刪除,但如果我在同一視圖的兩個分支之間切換,我的列表項目會得到這個奇怪的前導填充。
不確定如何准確解釋它,所以我附上了發生的事情。
這是我的列表行代碼:
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")
}
這里有一些想法:
moviesVM
- 我們不在 SwiftUI 中使用視圖 model 對象。對於瞬態視圖數據,我們使用帶有@State
和@Binding
的視圖結構,這使得結構值類型實際上表現得像 object,因為當結構再次初始化時,它會自動具有與上次初始化時相同的屬性值。 我們確實使用 object 來管理我們的 model 數據結構或 arrays 的生命周期,在我們使用environmentObject
傳遞給視圖的ObservableObject
的@Published
屬性中。ForEach(Array(
- ForEach
View 需要提供您的 model 數據才能正常工作,這通常是一個符合Identifiable
的結構數組。例如ForEach($model.movies) $movie in
我們想要寫入訪問權限時。MovieListRow(moviesVM MoviesViewModel(
- 像這樣在body
中初始化對象是錯誤的,這會減慢 SwiftUI 並導致 memory 泄漏。在 body 中,我們只初始化超快速值類型的視圖數據結構。body func 被反復調用,之后SwiftUI 已經區分並更新了屏幕上的標簽等所有這些視圖結構都被丟棄了。body
太大了,我們應該用少量的let
或@State
將它分解成小的視圖。 這稱為嚴格失效。 原因是 SwiftUI 具有依賴性和更改跟蹤功能,如果正文太大,則效率不高。 命名結構可能會很棘手,因為它們是基於數據而不是屏幕區域,從ContentView1
、 ContentView2
等開始,直到您找到一個好的命名方案,例如一些基於屬性的命名視圖。推薦觀看SwiftUI中的WWDC 2020 Data Essentials,學習正確使用SwiftUI。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.