软件测试之性能测试(ios)——UINavigationBar的返回按钮识别

本文深入解析iOS中UINavigationController与UINavigationBar的关系,探讨不同场景下返回按钮的实现方式,包括自定义按钮、系统默认按钮及按钮展示顺序。

最近在研究ios 随身版monkey,monkey需要有发送back事件的能力。对于android实现比较简单,因为系统本身就支持back,但是ios本身不支持,这时候就需要寻找controller的返回按钮。

1、controller返回按钮的一般实现

要寻找controller的返回按钮,就需要了解controller是如何实现返回的,这里面先定义两个概念,即previousController和currentController,previousController表示前一个Controller,而currentController表示当前界面显示的Controller,关系如下图所示。
在这里插入图片描述

1.1 通过currentController的 self.navigationItem.leftBarButtonItems实现

通常使用leftBarButtonItems的方式是为了控制返回按钮的间距,一般常用代码模式如下:

 NSMutableArray *barItems = [NSMutableArray array];
 //距离左右的间距
 UIBarButtonItem *space = xxxx ;
 [barItems addObject:spacer];
 UIBarButtonItem *barItem;
 if(文字按钮){
	barItem = [[UIBarButtonItem alloc] initWithTitle:xxx style:UIBarButtonItemStylePlain target:self action:xxxx];
 }else if(图片按钮){
	barItem = [[UIBarButtonItem alloc] initWithCustomView:xxxx];
 }
 [barItems addObject:barItem];
 self.navigationItem.leftBarButtonItems = barItems

1.2 通过currentController的self.navigationItem.leftBarButtonItem实现

使用 leftBarButtonItem的方式应该是最常用的自定义返回按钮的一种方式,常用代码模式如下:

 UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithCustomView:xxx];
 self.navigationItem.leftBarButtonItem = item;

或者

 UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithTitle:xxx style:UIBarButtonItemStylePlain target:self action:xxxx];
 self.navigationItem.leftBarButtonItem = item;

1.3 通过previousController的self.navigationItem.backBarButtonItem实现

使用 backBarButtonItem的方式应该是自定义返回按钮的另一种方式,常用代码模式如下:

 UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithCustomView:xxx];
 self.navigationItem.backBarButtonItem= item;

或者

 UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithTitle:xxx style:UIBarButtonItemStylePlain target:self action:xxxx];
 self.navigationItem.backBarButtonItem= item;

1.4 没有自定义任何返回按钮,使用系统默认按钮

在按钮上显示的文字规则如下:

  • 如果previousController有标题(title),则currentController的返回按钮将自动变为该标题
  • 如果previousController没有标题(title),在中文环境下,显示“返回”,在英文环境下,显示“Back”

2、UINavigationBar与UINavigationItem的关系

UINavigationController负责创建、配置及管理UINavigationBar, 其通过位于UIViewController堆栈栈顶位置的UIViewController的navigationItem属性来管理UINavigationBar展示的内容, 同时UINavigationController也提供了navigationBar属性, 允许开发者通过该属性设置UINavigationBar的外观。

通俗来讲就是前面通过self.navigationItem进行赋值自定义的返回按钮,其实体现在了 self.navigationController.navigationBar上

self.navigationItem与self.navigationController.navigationBar的对应关系如下图所示:
在这里插入图片描述
下面用等号来表示他们之间的对应关系

self.navigationController.navigationBar.topItem.leftBarButtonItems =  self.navigationItem.leftBarButtonItems
self.navigationController.navigationBar.topItem.leftBarButtonItem = self.navigationItem.leftBarButtonItem
self.navigationController.navigationBar.backItem.backBarButtonItem = self.navigationItem.backBarButtonItem
self.navigationController.navigationBar.topItem.rightBarButtonItem = self.navigationItem.rightBarButtonItem

3、寻找controller的返回按钮

知道以上原理以后,接下来就是寻找位于左侧返回按钮展示内容的顺序。顺序如下所示:

  • 如果topItem设置了左侧按钮组(leftBarButtonItems属性), 则展示左侧按钮组的最后一个UIBarButtonItem
  • 如果topItem设置了左侧按钮(leftBarButtonItem属性), 则展示左侧按钮
  • 如果backItem设置了返回按钮(backBarButtonItem属性), 则展示返回按钮
  • 如果backItem设置了标题文字(title属性), 则展示利用标题文字封装的返回按钮
  • 如果以上都未设置, 在中文环境下,显示“返回”,在英文环境下,显示“Back”

4、代码如下

  //如果topItem设置了左侧按钮组(leftBarButtonItems属性),则默认使用最后一个item
    //如果topItem设置了左侧按钮(leftBarButtonItem属性), 则展示左侧按钮
    //如果backItem设置了返回按钮(backBarButtonItem属性), 则展示返回按钮
    //如果backItem设置了标题文字(title属性), 则展示利用标题文字封装的返回按钮
    //如果当前是中文环境,则展示利用文字”返回”封装的返回按钮
    //如果当前是英文环境,则展示利用文字”Back”封装的返回按钮
    NSString *back = nil ;
    if([FindTopController topController].navigationController.navigationBar.topItem.leftBarButtonItems){
        UIBarButtonItem *item = [[FindTopController topController].navigationController.navigationBar.topItem.leftBarButtonItems lastObject] ;
        //返回按钮是由UIBarButtonItem的initWithCustomView定义
        if(item.customView){
            back = item.customView.accessibilityLabel ;
        }else{
            //如果定义了title
            if(item.title){
                back = item.title ;
            }
        }
    }else if([FindTopController topController].navigationController.navigationBar.topItem.leftBarButtonItem){
        
        //返回按钮是由UIBarButtonItem的initWithCustomView定义
        if([FindTopController topController].navigationController.navigationBar.topItem.leftBarButtonItem.customView){
            back = [FindTopController topController].navigationController.navigationBar.topItem.leftBarButtonItem.customView.accessibilityLabel ;
        }else{
           //如果定义了title
           if([FindTopController topController].navigationController.navigationBar.topItem.leftBarButtonItem.title){
               back = [FindTopController topController].navigationController.navigationBar.topItem.leftBarButtonItem.title ;
           }
        }
    }else if([FindTopController topController].navigationController.navigationBar.backItem.backBarButtonItem){
        
        //返回按钮是由UIBarButtonItem的initWithCustomView定义
        if([FindTopController topController].navigationController.navigationBar.backItem.backBarButtonItem.customView){
            back = [FindTopController topController].navigationController.navigationBar.backItem.backBarButtonItem.customView.accessibilityLabel ;
        }else{
            //如果定义了title
           if([FindTopController topController].navigationController.navigationBar.backItem.backBarButtonItem.title){
               back = [FindTopController topController].navigationController.navigationBar.backItem.backBarButtonItem.title ;
           }
        }
    }else if([FindTopController topController].navigationController.navigationBar.backItem.title){
        back = [FindTopController topController].navigationController.navigationBar.backItem.title ;
    }else{
        //获取当前语言环境
        NSArray *languages = [NSLocale preferredLanguages] ;
        NSString* preferredLang = [languages objectAtIndex:0];
        
        //判断当前app是否支持中文环境
        NSString *path = [[NSBundle mainBundle] pathForResource:@"zh-Hans" ofType:@"lproj"];
        if(path){
            back = @"返回" ;
        }else{
            back = @"Back" ;
        }
    }

5、另外一种更加优雅的方式返回

   if (self.presentingViewController) {
        [self dismissViewControllerAnimated:YES completion:nil];
    } else {
        [self.navigationController popViewControllerAnimated:YES];
    }

6、参考文章

1、http://www.liupeng.tech/2017/02/16/UINavigationController%E4%B8%8EUINavigationBar%E8%AF%A6%E8%A7%A3/
2、https://blog.novoda.com/ui-testing-part-2/
3、https://blog.youkuaiyun.com/moon_prince2013/article/details/49079251
4、https://www.jianshu.com/p/32418956c322

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值