浅谈TabBar封装及项目实践

最近一次项目(电商类)遇到了这样的需求:

TabBar有3个页面,第一个首页是购物页面,购物完成会跳转到成功或失败页面(后续需求根据这个展开),第二个页面是我的订单页,展示所有订单,如果购物未支付,在我的订单页可以继续支付,然后跳转到成功或失败页面。

支付成功或失败页面,没有返回按钮,只有三个按钮,查看订单详情、联系客服、返回首页。


现在开始介绍需求:

之后只说成功页,因为失败页除了和成功页长的不一样,三个按钮是一样的。

需求一:点击返回首页,跳转到首页。

需求二:点击查看订单按钮,跳转到订单详情页,点击返回按钮,返回到订单列表页并且自动刷新(就是TabBar的第二个我的订单页面)。


功能实现情况详解:

需求一:

情况1、从首页一直push到成功页面,点击返回首页,正常通过Nav(导航)pop返回就好了。

情况2、从订单列表或订单详情页(TabBar第二个页面)通过支付push到成功页面,点击返回首页,在这时无法通过Nav(导航)返回因为不是一个控制器,想返回首页需要更改TabBar的选中状态,然后更改按钮选中状态。

需求二:

情况1、从首页一直push到成功页面,点击订单详情页,点击返回按钮,在这时无法通过Nav(导航)返回因为不是一个控制器,想返回订单列表页需要更改TabBar的选中状态,然后更改按钮选中状态,并且调用下拉刷新。

情况2、从订单列表或订单详情页(TabBar第二个页面)通过支付push到成功页面,点击订单详情页,点击返回按钮,正常通过Nav(导航)pop返回就好了。


在实现过程中发现,无法通过代码更改按钮的选中状态,简单来讲就是当前页面显示为首页,但是首页按钮不是高亮的,订单按钮是高亮,询问过大牛给的答复大概意思是这样的,TabBar是添加到window上得,所以TabBar的线程是安全的,无法通过代码更改按钮状态。

解决思路,既然无法更改按钮的状态,那就更改window的root(希望能遇到大神给出更好的解决方法)。

我的TabBar是封装好的,所以在无法通过Nav返回页面时,创建一个新的TabBar,设置它的选中状态来达到自己的效果。

订单详情返回按钮代码块:

-(void)backPrePage{
    if (self.isJump) {
        for (UIViewController *vc in self.navigationController.childViewControllers) {
            if ([vc isKindOfClass:[SecondViewController class]]) {
                self.isJump = NO;
                [self.navigationController popToViewController:vc animated:YES];
                return;
            }
        }
    }
    
    
    UIWindow* window = [[UIApplication sharedApplication].delegate window];

    GZTabBarViewController* tabVc = [[GZTabBarViewController alloc] init];
     [tabVc confirmSelectTabBar:1];
    // 选择某个 自定义控制器
    NSArray *arr =  tabVc.bgView.subviews;
    [tabVc chooseTabBar:(UIButton *)arr[1]];
    [window setRootViewController:tabVc];

}

通过上面代码解决我所遇到的问题,但是有一些担心,当更改window的root后,旧的对象如何释放?会不会内存爆了?或者内存泄露的风险?

通过观察发现,iOS系统有自己的处理机制,会自动释放掉旧的对象,并且监测app运行时的内存,内存稳定在一定数值不会无限增加,验证了这个方法是可行的。

但是内存是否存在泄露,博主也是个新手希望大神能够指点指点。


下面是封装TabBar的代码:

.h文件

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
//第一页
#import "FirsrViewController.h"

@interface TabBarViewController : UITabBarController <UITabBarControllerDelegate,UINavigationControllerDelegate>{
    FirsrViewController *vc1;//首页
}

@property (nonatomic, strong) UIView *bgView; //tabBar 的 view
@property (nonatomic, assign) NSInteger beforeIndex; //之前的index
@property (nonatomic, assign) NSInteger presentIndex; //现在的index

//确定选择哪个 TabBar 选中与未选中的状态
-(void)confirmSelectTabBar:(NSInteger)sender;
//选择某个自定义控制器
-(void)chooseTabBar:(UIButton*)sender;

@end

.m文件

#define btn_tag 10001  // 设置5个按钮的tag值

#import "TabBarViewController.h"
//添加控制器
#import "SecondViewController.h"
#import "ThirdViewController.h"
#import "FourViewController.h"
#import "FifthViewController.h"
//导航控制器
#import "CustomNavController.h"


@interface TabBarViewController ()<UIGestureRecognizerDelegate>{
    NSArray *normal; //正常状态下tabBar图片集合
    NSArray *select; //选中状态下tabBar图片集合
}

@end

@implementation TabBarViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    //首页控制器 5个控制器
    vc1 = [[FirsrViewController alloc] init];
    SecondViewController *vc2 = [[SecondViewController alloc] init];
    ThirdViewController *vc3 = [[ThirdViewController alloc] init];
    FourViewController *vc4 = [[FourViewController alloc] init];
    FifthViewController *vc5 = [[FifthViewController alloc] init];
    //生成各个视图控制器-导航
    UINavigationController *nav1 = [[CustomNavController alloc] initWithRootViewController:vc1];
    UINavigationController *nav2 = [[CustomNavController alloc] initWithRootViewController:vc2];
    UINavigationController *nav3 = [[CustomNavController alloc] initWithRootViewController:vc3];
    UINavigationController *nav4 = [[CustomNavController alloc] initWithRootViewController:vc4];
    UINavigationController *nav5 = [[CustomNavController alloc] initWithRootViewController:vc5];
    
    //为扩展使用,如果是4个控制器,直接修改即可
    switch (TABBARCOUNT) {
        case 3:
            self.viewControllers = @[nav1,nav2,nav3];
            break;
        case 4:
            self.viewControllers = @[nav1,nav2,nav3,nav4];
            break;
        case 5:
            self.viewControllers = @[nav1,nav2,nav3,nav4,nav5];
            break;
        default:
            break;
    }
    
    //设置frame
    self.bgView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, UI_SCREEN_WIDTH, UI_TAB_BAR_HEIGHT)];
    //背景颜色值
    _bgView.backgroundColor = UIColorFromRGB(0xf7f7f7);
    [self.tabBar addSubview:_bgView];
    //图片添加 遍历
    for (int i=0; i < TABBARCOUNT; i++) {
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
        btn.frame = CGRectMake(i*(UI_SCREEN_WIDTH / TABBARCOUNT), 0, (UI_SCREEN_WIDTH / TABBARCOUNT), UI_TAB_BAR_HEIGHT);
        normal = @[@"Home.png",@"Order.png",@"My.png"];
        select = @[@"Home1.png",@"Order1.png",@"My1"];
        //设置tag值
        btn.tag = btn_tag+i;
        //将程序进去默认选择第0个
        if (i == DEFAULTSELECTINDEX) {
            btn.selected = YES;
            _beforeIndex = i;
            _presentIndex = i;
        }
        //设置按钮背景图片
        [btn setImage:[UIImage imageNamed:normal[i]] forState:UIControlStateNormal];
        [btn setImage:[UIImage imageNamed:select[i]] forState:UIControlStateSelected];
        //取消按钮点击效果(点击后变灰)
        btn.adjustsImageWhenHighlighted = NO;
        [_bgView addSubview:btn];
        
        [btn addTarget:self action:@selector(chooseTabBar:) forControlEvents:UIControlEventTouchUpInside];
    }

}

#pragma mark - 选择某个自定义控制器
//选择某个自定义控制器
-(void)chooseTabBar:(UIButton *)sender{
    _presentIndex = sender.tag - btn_tag;
    switch (_presentIndex) {
        case 0:
            {
                GZLOG(@"%ld",(long)_presentIndex);
                [self confirmSelectTabBar:_presentIndex];
                [self setSelectedIndex:_presentIndex];
                _beforeIndex = _presentIndex;
                break;
            }
        case 1:
            {
                GZLOG(@"%ld",(long)_presentIndex);
                [self confirmSelectTabBar:_presentIndex];
                [self setSelectedIndex:_presentIndex];
                _beforeIndex = _presentIndex;
                break;
            }
        case 2:
            {
                GZLOG(@"%ld",(long)_presentIndex);
                [self confirmSelectTabBar:_presentIndex];
                [self setSelectedIndex:_presentIndex];
                _beforeIndex = _presentIndex;
                break;
            }
        case 3:
            {
                GZLOG(@"%ld",(long)_presentIndex);
                [self confirmSelectTabBar:_presentIndex];
                [self setSelectedIndex:_presentIndex];
                _beforeIndex = _presentIndex;
                break;
            }
        case 4:
            {
                GZLOG(@"%ld",(long)_presentIndex);
                [self confirmSelectTabBar:_presentIndex];
                [self setSelectedIndex:_presentIndex];
                _beforeIndex = _presentIndex;
                break;
            }
        
        default:
            break;
    }
    
    //点击抖动动画
    CGPoint oldAnchorPoint = sender.layer.anchorPoint;
    sender.layer.anchorPoint = CGPointMake(0.5, 0);
    [sender.layer setPosition:CGPointMake(sender.layer.position.x + sender.layer.bounds.size.width * (sender.layer.anchorPoint.x - oldAnchorPoint.x), sender.layer.position.y + sender.layer.bounds.size.height * (sender.layer.anchorPoint.y - oldAnchorPoint.y))];
    CABasicAnimation *shakeAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    shakeAnimation.duration = 0.07;
    shakeAnimation.fromValue = [NSNumber numberWithFloat:-0.05];
    shakeAnimation.toValue = [NSNumber numberWithFloat:0.05];
    shakeAnimation.autoreverses = YES;
    shakeAnimation.repeatCount = 2;
    shakeAnimation.removedOnCompletion = NO;
    [sender.layer addAnimation:shakeAnimation forKey:@"shakeAnimation"];
    
}

//确定选择哪个TabBar 选中与未选中状态
-(void)confirmSelectTabBar:(NSInteger)sender{
    for (UIButton *btn in [_bgView subviews]) {
        if ([btn isKindOfClass:[UIButton class]]) {
            if (btn.tag == sender+btn_tag) {
                btn.selected = YES;
            }else{
                btn.selected = NO;
            }
        }
    }
}










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值