如何将 accessibilityIdentifier 设置为 UIAlertController?

25
这是我简单创建UIAlertController并在屏幕上呈现它的方法:
private class func showAlertWithTitle(title: String, message: String) {

    let alert = UIAlertController(title: title, message: message, preferredStyle: .Alert)
    //alert.accessibilityLabel = "my string here"      //doesnt work
    let action = UIAlertAction(title: "OK", style: .Default) { action in
        alert.dismissViewControllerAnimated(true, completion: nil)
    }

    alert.addAction(action)
    UIStoryboard.topViewController()?.presentViewController(alert, animated: true, completion: nil)
}

以下是我在UITests中访问它的方式:

emailAlert = app.alerts["First Name"] //for title "First Name"

但我想设置自定义标识符并通过firstName访问它,就像这样:

emailAlert = app.alerts["firstName"]

这是可能的吗?

4个回答

15

这是一个旧的讨论串,但可能有人会用到这个。

我能够像这样设置可访问标识:


let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
alert.view.accessibilityIdentifier = "custom_alert"
alert.view.accessibilityValue = "\(title)-\(message)"

alert.addAction(
    UIAlertAction(
        title: "ALERT_BUTTON_OK".localized,
        style: .default,
        handler: handler
    )
)

present(alert, animated: true)

这样我就可以通过辅助标识符访问警报并检查其在辅助值中的内容。

当然,这并不是完美的解决方案,但它有效 - 至少对于我使用Appium进行测试而言。


我一直在寻找一种给警报一个特定标识符的方法。这就是我一直在寻找的答案。谢谢!哦,它在Swift 4中运行良好。 - Phontaine Judd
4
你写道你检查了它的内容,但是你如何检查按钮的文本?它没有无障碍标识。 - simpleuser

6
我找到的唯一方法是使用苹果的私有API。您可以在UIAlertAction对象上调用valueForKey方法,并使用这个超级秘密的键"__representer"来获取所谓的_UIAlertControllerActionView
    let alertView = UIAlertController(title: "This is Alert!", message: "This is a message!", preferredStyle: .Alert)
    let okAction = UIAlertAction(title: "OK", style: .Default, handler: nil)

    alertView.addAction(okAction)

    self.presentViewController(alertView, animated: true, completion: {
        let alertButton = action.valueForKey("__representer")
        let view = alertButton as? UIView
        view?.accessibilityIdentifier = "okAction_AID"
    })

必须在完成处理程序中完成此操作,因为_UIAlertControllerActionView直到显示视图后才存在。顺便说一下,在我的项目中,我使用以下扩展使事情更容易/更可读:

extension UIAlertController {
    func applyAccessibilityIdentifiers()
    {
        for action in actions
        {
            let label = action.valueForKey("__representer")
            let view = label as? UIView
            view?.accessibilityIdentifier = action.getAcAccessibilityIdentifier()
        }

    }

}

extension UIAlertAction
{
    private struct AssociatedKeys {
        static var AccessabilityIdentifier = "nsh_AccesabilityIdentifier"
    }

    func setAccessibilityIdentifier(accessabilityIdentifier: String)
    {
        objc_setAssociatedObject(self, &AssociatedKeys.AccessabilityIdentifier, accessabilityIdentifier, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
    }

    func getAcAccessibilityIdentifier() -> String?
    {
        return objc_getAssociatedObject(self, &AssociatedKeys.AccessabilityIdentifier) as? String
    }
}

因此,以上代码将被重写为:
    let alertView = UIAlertController(title: NSLocalizedString("NMN_LOGINPAGECONTROLLER_ERROR_TITLE", comment: ""), message: message as String, preferredStyle:.Alert)
    let okAction = UIAlertAction(title: NSLocalizedString("NMN_OK", comment: ""), style: .Default, handler: nil)
    okAction.setAccessibilityIdentifier(InvalidLoginAlertView_AID)


    alertView.addAction(okAction)


    self.presentViewController(alertView, animated: true, completion: {
        alertView.applyAccessibilityIdentifiers()
    })

我的第一次尝试是试图导航视图层次结构,但由于UIAlertControllerActionView不属于公共API的一部分,这变得困难了。无论如何,我可能会尝试为提交给应用商店的构建ifdef掉valueForKey("__representer"),否则苹果可能会惩罚你。


2
这个有用。我刚刚向苹果提交了一个错误报告,希望如果我们中的很多人投诉,他们会采取一些措施。 - user1366265
有任何想法如何为标题和消息设置可访问性标识符吗? - user1366265
对不起,我不确定。只需要为自动化目的设置可访问性标识符,所以从来没有需要访问标题或消息。 - Anthony Olds
谢谢 @AnthonyOlds!它对我有用。但我有一个问题,为什么你使用了“__representer”?有没有相关文档? - Prema Janoti
我认为这些键没有文档记录,但我从这个Stack Overflow问题的被接受答案中学到了这个特定键会起作用:https://dev59.com/Yl8d5IYBdhLWcg3wxUjC#36136625 - Anthony Olds
显示剩余2条评论

1

现在我有一个名为addCameraUIAlertAction,我只是这样做:

addCamera.accessibilityLabel = "camera-autocomplete-action-photo"

这使得我可以在UI测试中轻松点击它:

app.sheets.buttons["camera-autocomplete-action-photo"].firstMatch.tap()


17
对于那些真正需要辅助功能帮助的人来说,这非常没有帮助。 - idrougge
在测试中,您不应使用“编程命名”的标签,因为启用辅助功能的用户会读取它们,而应使用辅助功能标识符。 - kikeenrique

-1

来自苹果文档...

https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/UIKitUICatalog/UIAlertView.html

让警报视图易于访问

警报视图默认是可访问的。 对于警报标题、警报消息和按钮标题的无障碍功能。如果激活了VoiceOver,则当显示警报时,它将发音“alert”,然后发音其标题并跟随其消息(如果设置)。当用户点击一个按钮时,VoiceOver会说出按钮的标题和单词“button”。当用户点击文本框时,VoiceOver会说出它的值以及“text field”或“secure text field”。


4
此处未提及如何设置可访问性标识符。 - user1366265
不是的,但这是苹果推荐访问警报的方式。 - tanya
5
这很糟糕,特别是涉及本地化过程。 - Zonily Jame
2
该文本讨论了使警报对用户可访问,这与使用accessibilityIdentifier来访问它们进行UI测试只有轻微的关联。accessibilityIdentifier除了名称相似性之外,与其他accessibility*项没有任何实际关系;用户根本不使用它。 - simpleuser
2
这是关于UIAlertViews而不是UIAlertController的讨论,与问题无关。 - Alaa Eddine Cherbib

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接