单元格列表与LazyVGrid有时消失



我有这个:

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

嗯,这个假设是错误的。我现在对问题的结构理解得更清楚了。

点击其中一个AlbumItemsScreenCell将导航到一个详细信息屏幕(我已经添加到上面的代码中以显示这一点)。在详细信息屏幕中,用户操作可以导致评论计数重置,从而发送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)
}
}

Notification被接收时,unreadCountBadgeText被观察者改变(在主线程上)。

因此,总的来说,单元格上的徽章被更改,而不显示单元格的屏幕—显示详细信息屏幕。

我一直在使用以下条件修饰语:

extension View {
public func enabled(_ enabled: Bool) -> some View {
return self.disabled(!enabled)
}

// https://forums.swift.org/t/conditionally-apply-modifier-in-swiftui/32815/16
@ViewBuilder func `if`<T>(_ condition: Bool, transform: (Self) -> T) -> some View where T : View {
if condition {
transform(self)
} else {
self
}
}
}

AlbumItemsScreenCell上显示徽章。

原来的徽章是这样的:

extension View {
func upperLeftBadge(_ badgeText: String) -> some View {
return self.modifier(UpperLeftBadge(badgeText))
}
}
struct UpperLeftBadge: ViewModifier {
let badgeText: String
init(_ badgeText: String) {
self.badgeText = badgeText
}
func body(content: Content) -> some View {
content
.overlay(
ZStack {
Badge(badgeText)
}
.padding([.top, .leading], 5),
alignment: .topLeading
)
}
}

。,单元格中的用法如下所示:

.if(condition) {
$0.upperLeftBadge(badgeText)
}

当我改变修饰符来使用它与这个.if修饰符,并直接使用它,问题就消失了:

extension View {
func upperLeftBadge(_ badgeText: String?) -> some View {
return self.modifier(UpperLeftBadge(badgeText: badgeText))
}
}
struct UpperLeftBadge: ViewModifier {
let badgeText: String?
func body(content: Content) -> some View {
content
.overlay(
ZStack {
if let badgeText = badgeText {
Badge(badgeText)
}
}
.padding([.top, .leading], 5),
alignment: .topLeading
)
}
}

这可能听起来很奇怪,但在我的tvOS应用程序中,我禁用了动画和单元格(视图)停止消失所以试着删除.animation(.easeInOut)

相关内容

  • 没有找到相关文章

最新更新