UITabBarButton无法正确识别accessibilityIdentifier问题求助
我之前开发时也碰到过一模一样的问题!iOS 9里用纯代码创建TabBar、只设置tabBarItem图片并绑定accessibilityIdentifier完全正常,但到了iOS 10就死活读不到这个标识符,当时折腾了好一阵才找到解决办法。
问题原因分析
后来查了下,这应该是iOS 10的一个系统小bug:当UITabBarItem没有设置title(包括title为nil)时,系统内部没有正确将accessibilityIdentifier关联到对应的TabBar按钮上,导致自动化测试或者代码里无法通过identifier定位到元素。
可行的解决方案
这里分享几个亲测有效的办法:
1. 给tabBarItem设置空字符串title(最推荐)
不需要显示title,但可以先给title赋值为空字符串,再设置accessibilityIdentifier,iOS 10就能正确识别了:
// Swift版本 let tabItem = UITabBarItem(title: "", image: UIImage(named: "tab-icon"), selectedImage: UIImage(named: "tab-icon-selected")) tabItem.accessibilityIdentifier = "home-tab-item"
// Objective-C版本 UITabBarItem *tabItem = [[UITabBarItem alloc] initWithTitle:@"" image:[UIImage imageNamed:@"tab-icon"] selectedImage:[UIImage imageNamed:@"tab-icon-selected"]]; tabItem.accessibilityIdentifier = @"home-tab-item";
这个方法不会影响UI显示(空字符串title不会占空间),又能让accessibilityIdentifier正常生效,是最稳妥的方案。
2. 直接给TabBar的按钮子视图设置identifier
如果上面的方法不行,可以直接遍历TabBar的subviews,找到对应的UITabBarButton(这是私有类,iOS 10里可通过类名判断),然后给它设置accessibilityIdentifier:
// Swift版本 for subview in tabBar.subviews { if subview.isKind(of: NSClassFromString("UITabBarButton")!) { // 可通过tag或位置区分不同tab按钮 if subview.tag == 0 { subview.accessibilityIdentifier = "home-tab-button" } } }
// Objective-C版本 for (UIView *subview in self.tabBar.subviews) { if ([subview isKindOfClass:NSClassFromString(@"UITabBarButton")]) { if (subview.tag == 0) { subview.accessibilityIdentifier = @"home-tab-button"; } } }
不过因为UITabBarButton是私有API,后续系统版本可能有变化,所以这个方法作为备选方案更合适。
3. 延迟设置accessibilityIdentifier
有时候系统初始化TabBarItem的时机在iOS 10里有延迟,可以尝试在viewDidAppear或者延迟执行中再设置identifier:
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { self.tabBar.items?.first?.accessibilityIdentifier = "home-tab-item" }
这个方法偶尔能解决时序问题,但稳定性不如第一个方案。
总结
这个问题在iOS 10之后的版本(比如iOS 11+)已经被Apple修复了,所以如果你的APP只需要兼容iOS 11及以上,其实不用管这个问题,但如果要兼容iOS 10,最推荐的还是给tabBarItem设置空字符串title的方法,简单又可靠。
内容的提问来源于stack exchange,提问作者Chetan kasundra

