Swift如何通过辅助功能画外音引擎了解当前关注的对象

Swift如何通过辅助功能画外音引擎了解当前关注的对象,swift,notifications,accessibility,nsnotificationcenter,Swift,Notifications,Accessibility,Nsnotificationcenter,我需要知道可访问性焦点引擎当前关注哪个元素。在一个简单的例子中,让我们假设我是带着两个标签来的。我需要知道,例如,在控制台上打印,或者做其他事情,哪个对象当前被聚焦。如果我有一个有很多不同类型子视图的视图,它们是相同的。我认为我应该使用elementFocusedNotification,并且如文档中所述,使用键UIAccessibilityElementFocusedKeyElement。我想我应该在方法中传递对象,但是如何传递呢 在其他人中,我寻找了一些信息,但找不到解决方案来知道当前关注的

我需要知道可访问性焦点引擎当前关注哪个元素。在一个简单的例子中,让我们假设我是带着两个标签来的。我需要知道,例如,在控制台上打印,或者做其他事情,哪个对象当前被聚焦。如果我有一个有很多不同类型子视图的视图,它们是相同的。我认为我应该使用elementFocusedNotification,并且如文档中所述,使用键UIAccessibilityElementFocusedKeyElement。我想我应该在方法中传递对象,但是如何传递呢

在其他人中,我寻找了一些信息,但找不到解决方案来知道当前关注的是哪个元素

在我的cellForRowAt Indexath中:

在单元格中:

override func accessibilityElementDidBecomeFocused() {
        NotificationCenter.default.post(
            name: NSNotification.Name(rawValue: UIAccessibility.elementFocusedNotification.rawValue),
            object: self.subviews.first(where: {$0.isFocused}),
            userInfo: ["UIAccessibilityElementFocusedKeyElement": "hello there"]
        )
    }
在控制器的viewDidLoad中:

    NotificationCenter.default.addObserver(
        self,
        selector: #selector(self.doSomething(_:)),
        name: NSNotification.Name(rawValue: UIAccessibility.elementFocusedNotification.rawValue),
        object: nil
    )
在同一控制器中

@objc func catchNotification(_ notification: Notification) {
    //print("subscribed, notification: \(notification)")

    if let myNotification1 = notification.userInfo?["UIAccessibilityElementFocusedKeyElement"] {
        print("+++", myNotification1)
    }

   }    

这不是对你问题的直接回答,我也不确定这一切是否如我所说的那样有效。因为苹果隐藏了很多关于易访问性引擎工作原理的细节,但仍然可以从一个完全不同的角度帮助解决您的问题,而且您不需要知道当前的焦点是什么

看看苹果自己的一些应用程序。e、 g.设置应用程序。只能访问整个单元格。这些标签不是

解决办法是:

基于标签覆盖单元格的accessibilityLabel,然后将标签的isAccessibilityElement设置为false。有关更多信息,请参见。向下滚动至“增强表视图的可访问性” 只需在必要时手动设置accessibilityLabel,然后将标签的isAccessibilityElement设置为false。显然,如果标签更新,此解决方案将要求您重置它。 如果为accessoryView设置视图或文本,我相信UITableViewCell也会考虑其值。欲了解更多信息,请参阅
注意:tableviewcell的accessibilityLabel将默认为其标签的文本

首先,细胞永远不会聚焦

画外音关注单个可访问性元素,不通知其超级视图。 因此,如果要使用AccessibilityElementDibEcomeFocused,则必须重写UILabel

UIAccessibility.element FocusedNotification是由系统发送的,您可能永远不应该自己发布它

回到你的问题上来。 我想你有以下情况:

无论何时VO焦点标签或视图,您都希望通知您的控制器第i个元素已聚焦

我的做法如下:

class MyViewController ... {
    private var VOFocusChanged: NSObjectProtocol?

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        VOFocusChanged = NotificationCenter.default.addObserver(
            forName: UIAccessibility.elementFocusedNotification,
            object: nil,
            queue: OperationQueue.main
        ) {
            [weak self] (notification: Notification) in
            self?.handleVONotification(notification)
        }
    }
    
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        
        // there is no reason to observe changes 
        // if we know that view is no longer visible
        if let VOFocusChanged: NSObjectProtocol = VOFocusChanged {
            NotificationCenter.default.removeObserver(VOFocusChanged)
        }
    }
   
    private func handleVONotification(_ notification: Notification) {
        if let focusedView: UIView = notification.userInfo?[
                UIAccessibility.focusedElementUserInfoKey
            ] as? UIView {

            if focusedView.isGrandson(of: view) {
                if let fView: ViewWithElement = focusedView as? ViewWithElement {
                    elementsWasFocused(fView.element)
                }
            }
        }

    }
    
    private func elementsWasFocused(_ element: T) {
        // add your logic here
    }
 
}

extension UIView {
    func isGrandson(of view: UIView) -> Bool {
        if superview === view {
            return true
        }
        return superview?.isGrandson(of: view) ?? false
    }
}


protocol ViewWithElement {
    var element: T { get }
}

// Use this instead of label inside UITableViewCell 
class MyLabel: UILabel, ViewWithElement {

    func display(element: T) {
        _element = element
        text = ...
        accessibilityLabel = ...
    }
    // MARK: ViewWithElement
    private var _element: T!
    
    var element: T { return _element }
}

每个可访问性元素都应该知道显示的是哪个元素 视图控制器捕获每个通知,检查它是否由TableView的子视图发送,如果是,则从中获取元素 代码如下:

class MyViewController ... {
    private var VOFocusChanged: NSObjectProtocol?

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        VOFocusChanged = NotificationCenter.default.addObserver(
            forName: UIAccessibility.elementFocusedNotification,
            object: nil,
            queue: OperationQueue.main
        ) {
            [weak self] (notification: Notification) in
            self?.handleVONotification(notification)
        }
    }
    
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        
        // there is no reason to observe changes 
        // if we know that view is no longer visible
        if let VOFocusChanged: NSObjectProtocol = VOFocusChanged {
            NotificationCenter.default.removeObserver(VOFocusChanged)
        }
    }
   
    private func handleVONotification(_ notification: Notification) {
        if let focusedView: UIView = notification.userInfo?[
                UIAccessibility.focusedElementUserInfoKey
            ] as? UIView {

            if focusedView.isGrandson(of: view) {
                if let fView: ViewWithElement = focusedView as? ViewWithElement {
                    elementsWasFocused(fView.element)
                }
            }
        }

    }
    
    private func elementsWasFocused(_ element: T) {
        // add your logic here
    }
 
}

extension UIView {
    func isGrandson(of view: UIView) -> Bool {
        if superview === view {
            return true
        }
        return superview?.isGrandson(of: view) ?? false
    }
}


protocol ViewWithElement {
    var element: T { get }
}

// Use this instead of label inside UITableViewCell 
class MyLabel: UILabel, ViewWithElement {

    func display(element: T) {
        _element = element
        text = ...
        accessibilityLabel = ...
    }
    // MARK: ViewWithElement
    private var _element: T!
    
    var element: T { return _element }
}


你的“在我的手机里”是什么?你忘了写下来,我想你可以观察到重点项目的变化。尝试观察UIAccessibilityVoiceOverStatusIDChangeNotification,然后查看其用户信息中的内容