Home > database >  How to detect that a certain view is being displayed on screen in SwiftUI
How to detect that a certain view is being displayed on screen in SwiftUI

Time:04-08

I'm struggling with how to detect that a certain view is being displayed on the screen.

I have a notifications list in which new notification cells have blue backgrounds, and 2 seconds after you see the notification, the background changes to white, meaning you've seen that new notification, just like in Twitter's new notification screen.

First I thought about using the onAppear modifier to detect whether you've seen the new notification cell, but it gets triggered before the particular cell is being displayed on the screen.

So I thought up a workaround. When the notifications bottom tab is selected, i.e. when the user comes to the notifications view from another view, then 2 seconds later change the background of the new notification cell.


struct NotificationCell: View {

@Binding var tabSelection: TabBarItem
@Binding var notificationsDetail: NotificationsDetail

var body: some View {

HStack {
 //Views inside
}
.background(notificationsDetail.notificationsIsAlreadyRead ? .white : .blue)

 }
}

However, I don't know where to write the following code because init() or onAppear gets triggered only once at the beginning. I need to make sure I run the code when the tabSelection property changes.

  if tabSelection == .notifications {
                DispatchQueue.main.asyncAfter(deadline: .now()   2.0) {
                    notificationsDetail.notificationsIsAlreadyRead = true
                }
            }

I've also studied onChange modifier but since I'm not using Texts or TexFields I thought onChange might not fit as a solution here.

Maybe my workaround is not a good approach in the first place to achieving what I want to do.

Any advice would be highly appreciated.

Thanks in advance.

CodePudding user response:

onChange is what would work here.

.onChange(of: tabSelection) { selection in
    if selection == .notifications {
        DispatchQueue.main.asyncAfter(deadline: .now()   2) {
            notificationsDetail.notificationsIsAlreadyRead = true
        }
    }
}    
  • Related