【问题标题】:How to find a SwiftUI view with custom tag or accessibility identifier?如何找到带有自定义标签或可访问性标识符的 SwiftUI 视图?
【发布时间】:2021-01-29 00:24:00
【问题描述】:

这是示例代码(使用Introspect 包):

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

为什么tagaccessibilityIdentifier 没有正确传播到底层视图层次结构?

【问题讨论】:

  • 相反的问题:为什么应该这样做?
  • 我知道从技术上讲它不是同一个视图,但我有点希望它能够工作,因为我还能在层次结构中找到特定的 SwiftUI 视图以获取它的框架并执行滚动没有ScrollViewReader(为了也支持iOS 13)?

标签: ios swift swiftui uikit introspection


【解决方案1】:

无论如何,解决这个问题的方法非常简单:

  • 由于“标记”视图可以很好地与 UIKit 视图配合使用(即使包装在 UIViewRepresentable 中),这个简单的包装器可以提供帮助:
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
    }
}
  • 那么我们可以将其添加到包含已标记 UIKit 视图的先前包装器的 ZStack 中,而不是尝试直接标记 SwiftUI 视图,稍后可以使用 viewWithTag(_:) 在视图层次结构中找到它:
ZStack {
    TagView(tag: 123)
    Text("Hello, world!")
}

【讨论】:

  • 我真的不确定这是否是正确的解决方案,如果我填充了 10 和 1000 的视图怎么办。只是好奇是否有更好的方法。
  • 在 UIKit 中使用标签通常被认为是一种糟糕的做法,并且在幕后会影响性能。这是巨大的代码气味,我不接受上述作为适当的答案。 UIKit 标记!= SwiftUI 标记。
  • 我同意这不是最好的解决方案,但它是我为这个特定用例找到的唯一一个(当你必须在 SwiftUI 层次结构中找到一些视图时)所以我只是分享了我的解决方案.这为我解决的情况是以编程方式滚动到使用 SwiftUI 1 (iOS 13) 的特定视图,其中没有 ScrollViewReader 可用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-04
  • 2018-12-28
  • 1970-01-01
相关资源
最近更新 更多