當你創建一個繼承與UITabBarController的子類 並想給其自定義構造方法 傳一些值的時候這時候問題出現了:
在創建的時候里面的init方法回調用了 viewdidload,導致每次傳值的時候都會在viewdidload加載完了之后傳的值才能傳過去
如下代碼
- (instancetype)initWithURLStrings:(NSArray *)urls{ self = [super init];//在調用init的時候回調用viewDidLoad 導致參數傳入進來時已經加載完了 if (self) {
self.urls = urls; } return self; } - (void)viewDidLoad { [super viewDidLoad]; [self setUpChild]; self.tabBar.backgroundColor = [UIColor whiteColor]; } - (void)setUpChild{ // 1.初始化子控制器 KHHomeVC *home = [[KHHomeVC alloc] initWithURL:self.urls[0]]; [self addChildVc:home title:@"首頁" image:@"tab_home_n" selectedImage:@"tab_home_s"]; KHVipVC *vipVC = [[KHVipVC alloc] initWithURL:self.urls[1]]; [self addChildVc:vipVC title:@"會員" image:@"tab_user_n" selectedImage:@"tab_user_s"]; KHMineDetailVC *settingVC = [[KHMineDetailVC alloc] initWithURL:self.urls[2]]; [self addChildVc:settingVC title:@"設置" image:@"tab_setting_n" selectedImage:@"tab_setting_s"]; } - (void)addChildVc:(UIViewController *)childVc title:(NSString *)title image:(NSString *)image selectedImage:(NSString *)selectedImage { // 設置子控制器的文字 childVc.title = title; // 同時設置tabbar和navigationBar的文字 // 設置子控制器的圖片 childVc.tabBarItem.image = [UIImage imageNamed:image]; if (iOS7) { childVc.tabBarItem.selectedImage = [[UIImage imageNamed:selectedImage] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; } else { childVc.tabBarItem.selectedImage = [UIImage imageNamed:selectedImage]; } // 設置文字的樣式 NSMutableDictionary *textAttrs = [NSMutableDictionary dictionary]; textAttrs[NSForegroundColorAttributeName] = [UIColor colorWithRed:136/255.0 green:136/255.0 blue:136/255.0 alpha:1]; NSMutableDictionary *selectTextAttrs = [NSMutableDictionary dictionary]; selectTextAttrs[NSForegroundColorAttributeName] = [UIColor colorWithRed:0 green:183/255.0 blue:283/255.0 alpha:1]; [childVc.tabBarItem setTitleTextAttributes:textAttrs forState:UIControlStateNormal]; [childVc.tabBarItem setTitleTextAttributes:selectTextAttrs forState:UIControlStateSelected]; // 先給外面傳進來的小控制器 包裝 一個導航控制器 KHNavigationController *nav = [[KHNavigationController alloc] initWithRootViewController:childVc]; nav.navigationBarHidden = YES; // 添加為子控制器 [self addChildViewController:nav]; }
這是怎么回事的 我們知道在一般控制器中我們想要自定義構造方法 會先走完初始化方法然后再走 viewDidLoad 但是這個UITabBarController怎么這么特殊呢呢?
經過一番查找終於知道了原來這是UITabBarController的一個特性
其實UITabBarController在init的時候,會增UITabbar到self.view,這時候必須加載self.view出來,從而就調用了loadview,進而調用viewdidload、viewwillappear等。這個是UITabBarController的特性
UITabBarController在調用【super init】的時候,系統調用了self.view的東西,但是此時view還沒加載出來,於是系統強制先調用viewdidload去加載self.view,最后加載完了,再接着走init方法中的 if(self)條件語句。
解決方案:
就是不要在viewdidload 方法里寫加載界面的代碼,可以單獨再寫個方法,直接在init結束的時候調用。所以我的建議就是直接把viewdidload和viewwillappear方法刪了,加載界面全都在init里寫,如下:
- (instancetype)initWithURLStrings:(NSArray *)urls{ self = [super init];//在調用init的時候回調用viewDidLoad 導致參數傳入進來時已經加載完了 if (self) { self.urls = urls; //初始化數據 [self setUpChild]; //這是解決的重點 } return self; } - (void)viewDidLoad { [super viewDidLoad]; self.tabBar.backgroundColor = [UIColor whiteColor]; } - (void)setUpChild{ // 1.初始化子控制器 KHHomeVC *home = [[KHHomeVC alloc] initWithURL:self.urls[0]]; [self addChildVc:home title:@"首頁" image:@"tab_home_n" selectedImage:@"tab_home_s"]; KHVipVC *vipVC = [[KHVipVC alloc] initWithURL:self.urls[1]]; [self addChildVc:vipVC title:@"會員" image:@"tab_user_n" selectedImage:@"tab_user_s"]; KHMineDetailVC *settingVC = [[KHMineDetailVC alloc] initWithURL:self.urls[2]]; [self addChildVc:settingVC title:@"設置" image:@"tab_setting_n" selectedImage:@"tab_setting_s"]; } - (void)addChildVc:(UIViewController *)childVc title:(NSString *)title image:(NSString *)image selectedImage:(NSString *)selectedImage { // 設置子控制器的文字 childVc.title = title; // 同時設置tabbar和navigationBar的文字 // 設置子控制器的圖片 childVc.tabBarItem.image = [UIImage imageNamed:image]; if (iOS7) { childVc.tabBarItem.selectedImage = [[UIImage imageNamed:selectedImage] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; } else { childVc.tabBarItem.selectedImage = [UIImage imageNamed:selectedImage]; } // 設置文字的樣式 NSMutableDictionary *textAttrs = [NSMutableDictionary dictionary]; textAttrs[NSForegroundColorAttributeName] = [UIColor colorWithRed:136/255.0 green:136/255.0 blue:136/255.0 alpha:1]; NSMutableDictionary *selectTextAttrs = [NSMutableDictionary dictionary]; selectTextAttrs[NSForegroundColorAttributeName] = [UIColor colorWithRed:0 green:183/255.0 blue:283/255.0 alpha:1]; [childVc.tabBarItem setTitleTextAttributes:textAttrs forState:UIControlStateNormal]; [childVc.tabBarItem setTitleTextAttributes:selectTextAttrs forState:UIControlStateSelected]; // 先給外面傳進來的小控制器 包裝 一個導航控制器 KHNavigationController *nav = [[KHNavigationController alloc] initWithRootViewController:childVc]; nav.navigationBarHidden = YES; // 添加為子控制器 [self addChildViewController:nav]; }
我發現只有繼承自UINavigationController和UITabBarController的類的init函數會產生loadView、viewDidLoad函數在初始化[super init]函數調用后就執行,一般UIViewController沒有這個問題
@implementation UIViewControllerSubclass - (id)init { NSLog(@"0"); if (self = [super init]) { NSLog(@"1"); } return self; } - (void)loadView { [super loadView]; NSLog(@"2"); } - (void)viewDidLoad { [super viewDidLoad]; NSLog(@"3"); } @end
console output
0 2 3 1
d