最近一次项目(电商类)遇到了这样的需求:
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;
}
}
}
}