tadija
tadija

Reputation: 3261

How to find a SwiftUI view with custom tag or accessibility identifier?

Here's the sample code (using Introspect package):

import SwiftUI
import Introspect

struct ContentView: View {
    let tag = 123
    let id = "abc"

    var body: some View {
        ScrollView {
            Text("Hello, world!")
                .tag(tag)
                .accessibility(identifier: id)
        }.introspectScrollView { (scrollView) in
            /// - Note: find with tag
            if scrollView.viewWithTag(tag) != nil {
                print("OK")
            } else {
                print("NOT OK")
            }
            /// - Note: find with accessibilityIdentifier
            if findViewWithID(id, in: scrollView) != nil {
                print("OK")
            } else {
                print("NOT OK")
            }
        }
    }

    func findViewWithID(_ id: String, in uiView: UIView) -> UIView? {
        if uiView.accessibilityIdentifier == id {
            return uiView
        }
        for view in uiView.subviews {
            if let view = findViewWithID(id, in: view) {
                return view
            }
        }
        return nil
    }
}

Why is tag or accessibilityIdentifier not propagated properly to the underlying view hierarchy?

Upvotes: 4

Views: 3919

Answers (1)

tadija
tadija

Reputation: 3261

Anyway, workaround for this turned out to be quite simple:

  • since "tagging" a view works just fine with UIKit view (even when wrapped in UIViewRepresentable) this simple wrapper comes to help:
struct TagView: UIViewRepresentable {
    let tag: Int

    func makeUIView(context: Context) -> UIView {
        let uiView = UIView()
        uiView.tag = tag
        return uiView
    }

    func updateUIView(_ uiView: UIView, context: Context) {
        uiView.tag = tag
    }
}
  • then instead of trying to tag SwiftUI view directly, we can just add it to a ZStack containing the previous wrapper of a tagged UIKit view, which can later be found in the view hierarchy using viewWithTag(_:):
ZStack {
    TagView(tag: 123)
    Text("Hello, world!")
}

Upvotes: 3

Related Questions