UITabBarController作为一个集合视图控制器,在很多APP上面都会用到,当app中有多个控制器的时候,就需要对这些控制器进行管理,用一个控制器去管理其他多个控制器。如图所示:
再使用的过程中我的项目中使用方式是
自定义TabBarController
//首页
HomePageViewController *homeVC = [[HomePageViewController alloc] init];
UIViewController *testVC = [[UIViewController alloc] init];
[self addChildViewController:homeVC title:@"首页" imageName:@"tabBar_icon_home_normal" selectImageName:@"tabBar_icon_home_selected"];
[self addChildViewController:applyVC title:@"test" imageName:@"tabBar_icon_test_normal" selectImageName:@"tabBar_icon_test_selected"];
//添加子控制器
- (void)addChildViewController:(UIViewController *)childController title:(NSString *)title imageName:(NSString *)imageName selectImageName:(NSString *)selectImageName {
//设置标题
childController.title = title;
UIImage * image = [UIImage imageNamed:[NSString stringWithFormat:@"%@",imageName]];
childController.tabBarItem.image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];;
UIImage * selectedImage = [UIImage imageNamed:[NSString stringWithFormat:@"%@",selectImageName]];
childController.tabBarItem.selectedImage = [selectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
UINavigationController * nav = [[UINavigationController alloc] initWithRootViewController:childController];
[self addChildViewController:nav];
}
在登录成功之后,进入主页
TZTabBarController * tabBarController = [[TZTabBarController alloc] init];
[UIApplication sharedApplication].keyWindow.rootViewController = tabBarController;
而HomePageViewController类里也实现
- (void)dealloc {
NSLog(@"%@ --- dealloc",self);
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
然而我在HomePageViewController的viewDidLoad里注册了通知,然后我重新登录操作,就发现了异常,仔细看没有其他地方注册这个通知,却出现通知两次。
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshMyDataNoti) name:@"RefreshRouteListNotice" object:nil];
}
经过排查由于之前的HomePageViewController的viewDidLoad里的通知没有被释放。导致通知注册了两次,可想而知如果我继续退出登录操作通知还会继续注册下去,因此我对在登录成功之后,进入主页进行了改善,
AppDelegate * app = (AppDelegate *)[UIApplication sharedApplication].delegate;
[app buildTabBarController];
[app setSelectTabPage:0];
在AppDelegate里懒加载自定义TabBarController,然后重新赋值给 [UIApplication sharedApplication].keyWindow.rootViewController便能解决再次触发HomePageViewController的viewDidLoad方法。
- (void)setSelectTabPage:(NSInteger)index {
self.tabBarController.selectedIndex = index;
}
但是上述方法也会出现tabbar一级页面刷新不及时的问题,因此这么使用的时候需要注意每个tabbar一级页面的刷新问题。
现在我们来深入思考下为什么不能在dealloc中调用
[[NSNotificationCenter defaultCenter] removeObserver:self];
在我们想添加观察者的时候,我们观察者的retainCount被引用计数+1了吗?
如果没有被引用计数+1,那么当这个类会在retainCount为0时被销毁,通知中心就无法通知到该类,那么remove方法还有意义吗?
所以在添加观察者的时候,通知中心必然会将该观察者的retainCount+1,
既然通知中心retain了这个观察者,那么很不幸,这个观察者的dealloc方法永远不会被调用,他的retainCount最少也是1,因为通知中心retain了一次,结果
[[NSNotificationCenter defaultCenter] removeObserver:self];
就永远不被调用。
如果您有其他的解决方案,欢迎留言一起交流,相互学习。