【发布时间】:2021-10-31 01:08:40
【问题描述】:
我有这个:
VStack {
List {
LazyVGrid(columns: gridItemLayout) {
ForEach(viewModel.objects, id: \.fileGroupUUID) { item in
AlbumItemsScreenCell(object: item, viewModel: viewModel, config: Self.config)
.onTapGesture {
switch viewModel.changeMode {
case .moving, .sharing, .moveAll:
viewModel.toggleItemToChange(item: item)
case .none:
object = item
viewModel.showCellDetails = true
}
}
.onLongPressGesture {
viewModel.restartDownload(fileGroupUUID: item.fileGroupUUID)
}
} // end ForEach
} // end LazyVGrid
}
.listStyle(PlainListStyle())
.refreshable {
viewModel.refresh()
}
.padding(5)
// Mostly this is to animate updates from the menu. E.g., the sorting order.
.animation(.easeInOut)
// Had a problem with return animation for a while: https://stackoverflow.com/questions/65101561
// The solution was to take the NavigationLink out of the scrollview/LazyVGrid above.
if let object = object {
// The `NavigationLink` works here because the `MenuNavBar` contains a `NavigationView`.
NavigationLink(
destination:
ObjectDetailsView(object: object, model: ObjectDetailsModel(object: object)),
isActive:
$viewModel.showCellDetails) {
EmptyView()
}
.frame(width: 0, height: 0)
.disabled(true)
} // end if
} // end VStack
AlbumItemsScreenCell:
struct AlbumItemsScreenCell: View {
@StateObject var object:ServerObjectModel
@StateObject var viewModel:AlbumItemsViewModel
let config: IconConfig
@Environment(\.colorScheme) var colorScheme
var body: some View {
AnyIcon(model: AnyIconModel(object: object), config: config,
emptyUpperRightView: viewModel.changeMode == .none,
upperRightView: {
UpperRightChangeIcon(object: object, viewModel: viewModel)
})
}
}
当用户点击其中一个单元格时,会导致导航到详细信息屏幕。有时当用户从该导航返回时,左上角的单元格会消失:
https://www.dropbox.com/s/mi6j2ie7h8dcdm0/disappearingCell.mp4?dl=0
我目前关于该问题的假设是,当该详细信息屏幕中的用户操作采取更改 viewModel.objects 的操作时,这会导致单元格消失问题。我很快就会检验这个假设。
----- 更新,11/1/21 ------
嗯,这个假设是错误的。我现在更清楚地了解了问题的结构。但仍然没有修复。
点击其中一个AlbumItemsScreenCells 导航到详细信息屏幕(我已添加到上面的代码中以显示这一点)。在详细信息屏幕中,用户操作可能会导致评论计数被重置,这会发送Notification。
AlbumItemsScreenCell 中的模型侦听这些通知(针对特定单元格)并重置单元格上的徽章。
这是那个模型:
class AnyIconModel: ObservableObject, CommentCountsObserverDelegate, MediaItemBadgeObserverDelegate, NewItemBadgeObserverDelegate {
@Published var mediaItemBadge: MediaItemBadge?
@Published var unreadCountBadgeText: String?
@Published var newItem: Bool = false
var mediaItemCommentCount:CommentCountsObserver!
let object: ServerObjectModel
var mediaItemBadgeObserver: MediaItemBadgeObserver!
var newItemObserver: NewItemBadgeObserver!
init(object: ServerObjectModel) {
self.object = object
// This is causing https://stackoverflow.com/questions/69783232/cell-in-list-with-lazyvgrid-disappears-sometimes
mediaItemCommentCount = CommentCountsObserver(object: object, delegate: self)
mediaItemBadgeObserver = MediaItemBadgeObserver(object: object, delegate: self)
newItemObserver = NewItemBadgeObserver(object: object, delegate: self)
}
}
unreadCountBadgeText 在收到Notification 时被观察者更改(在主线程上)。
因此,总而言之,单元格上的徽章会发生变化,而单元格的屏幕不会显示 - 会显示详细信息屏幕。
【问题讨论】:
-
你能加入minimal reproducible example吗?否则,任何人都无法运行您的代码并尝试帮助调试它。
-
看起来
AlbumItemsScreenCell中的 2@StateObject应该是@ObservedObject。一旦您向我们展示了一个可重现的最小示例,我们就会了解更多。