19

I have a view like below. I want to find out if it is the view which is displayed on the screen. Is there a function to achieve this?

struct TestView: View {
    var body: some View {
        Text("Test View")
    }
}
codezero11
  • 279
  • 3
  • 9
  • 1
    You want transfer proactive behaviour to reactive nature of SwiftUI. In SwiftUI concept some state (or in view model or in @State) determines whether view is visible or not. So having such state you don't need to ask view you use it directly. – Asperi Mar 09 '20 at 07:46
  • 1
    @Asperi It's not about setting the visibility, it's to check whether the view is currently inside the view port and if the user can see it. – Big_Chair Nov 13 '21 at 10:08

2 Answers2

15

You could use onAppear on any kind of view that conforms to View protocol.

struct TestView: View {
    @State var isViewDisplayed = false
    var body: some View {
        Text("Test View")
        .onAppear {
            self.isViewDisplayed = true
        }
        .onDisappear {
            self.isViewDisplayed = false
        }
    }

    func someFunction() {
        if isViewDisplayed {
            print("View is displayed.")
        } else {
            print("View is not displayed.")
        }
    }
}
shim
  • 8,356
  • 10
  • 70
  • 102
Frankenstein
  • 14,749
  • 4
  • 18
  • 44
  • Thanks but is there a way that I can do this inside a function, like `private func () { if (TestView.isDisplayed()) {do something}}`? – codezero11 Mar 09 '20 at 07:18
  • You need to specify that your requirement is to check if the view is displayed inside an external function. – Frankenstein Mar 09 '20 at 07:25
  • I've modified my answer according to your requirement. – Frankenstein Mar 09 '20 at 07:26
  • Thanks I have solved it. I will mark your answer as correct. :) – codezero11 Mar 09 '20 at 08:41
  • 22
    This is not really a displayed on screen. It will be call even if it doesn't show on the screen. Just by loading the view it will call `.onAppear()` – Oleg G. Nov 18 '20 at 18:52
  • https://stackoverflow.com/questions/1536923/determine-if-uiview-is-visible-to-the-user although this is not in swiftui. it is the sort of behavior expected. – Oleg G. Nov 18 '20 at 18:53
  • This isn't a great solution. If a fullscreencover happens and the underlying view disappears, onDisappear will not fire. – FontFamily Jun 01 '21 at 20:49
  • This will not work on iOS14 if you have the view inside a tabview / navigationview. There is a bug that calls onAppear immediately after onDisappear when you switch between tabs – Benzy Jun 23 '21 at 15:58
11

You can check the position of view in global scope using GeometryReader and GeometryProxy.

        struct CustomButton: View {
            var body: some View {
                GeometryReader { geometry in
                    VStack {
                        Button(action: {
                        }) {
                            Text("Custom Button")
                                .font(.body)
                                .fontWeight(.bold)
                                .foregroundColor(Color.white)
                        }
                        .background(Color.blue)
                    }.navigationBarItems(trailing: self.isButtonHidden(geometry) ?
                            HStack {
                                Button(action: {
                                }) {
                                    Text("Custom Button")
                                } : nil)
                }
            }

            private func isButtonHidden(_ geometry: GeometryProxy) -> Bool {
    // Alternatively, you can also check for geometry.frame(in:.global).origin.y if you know the button height.
                if geometry.frame(in: .global).maxY <= 0 {
                    return true
                }
                return false
            }
Seshu Vadlapudi
  • 111
  • 1
  • 4