iOS-自定義tabBarViewController- 以及關(guān)于添加,移除子控制器方法

本文會建一個自定義的tabBarController

--------------------------------------------

在開始之前乾忱,我們先了解一下? Adding and Removing a Child ?ViewController方法

先看一下SDK:

/*

These two methods are public for container subclasses to call when transitioning between child

controllers. If they are overridden, the overrides should ensure to call the super. The parent argument in

both of these methods is nil when a child is being removed from its parent; otherwise it is equal to the new

parent view controller.

addChildViewController: will call [child willMoveToParentViewController:self] before adding the

child. However, it will not call didMoveToParentViewController:. It is expected that a container view

controller subclass will make this call after a transition to the new child has completed or, in the

case of no transition, immediately after the call to addChildViewController:. Similarly

removeFromParentViewController: does not call [self willMoveToParentViewController:nil] before removing the

child. This is also the responsibilty of the container subclass. Container subclasses will typically define

a method that transitions to a new child by first calling addChildViewController:, then executing a

transition which will add the new child's view into the view hierarchy of its parent, and finally will call

didMoveToParentViewController:. Similarly, subclasses will typically define a method that removes a child in

the reverse manner by first calling [child willMoveToParentViewController:nil].

*/

- (void)willMoveToParentViewController:(UIViewController *)parent NS_AVAILABLE_IOS(5_0);

- (void)didMoveToParentViewController:(UIViewController *)parent NS_AVAILABLE_IOS(5_0);


蘋果新的API增加了addChildViewController方法芦缰,并且希望我們在使用addSubview時,同時調(diào)用[self addChildViewController:child]方法將sub view對應(yīng)的viewController也加到當(dāng)前ViewController的管理中榔袋。對于那些當(dāng)前暫時不需要顯示的subview,只通過addChildViewController把subViewController加進(jìn)去铡俐。需要顯示時再調(diào)用transitionFromViewController:toViewController:duration:options:animations:completion方法凰兑。

另外,當(dāng)收到系統(tǒng)的Memory Warning的時候审丘,系統(tǒng)也會自動把當(dāng)前沒有顯示的subview unload掉吏够,以節(jié)省內(nèi)存。


---------------------

然后下面是添加,移除锅知,轉(zhuǎn)換三個方法的實(shí)現(xiàn)


1.Adding another view controller’s view to the container’s view hierarchy

- (void) displayContentController: (UIViewController*) content;

{

[self addChildViewController:content];? ? ? ? ? ? ? ? // 1

content.view.frame = [self frameForContentController]; // 2

[self.view addSubview:self.currentClientView];

[content didMoveToParentViewController:self];? ? ? ? ? // 3

}

Here’s what the code does:

It calls the container’s addChildViewController: method to add the child. Calling the addChildViewController: method also calls the child’s willMoveToParentViewController: method automatically.

It accesses the child’s view property to retrieve the view and adds it to its own view hierarchy. The container sets the child’s size and position before adding the view; containers always choose where the child’s content appears. Although this example does this by explicitly setting the frame, you could also use layout constraints to determine the view’s position.

It explicitly calls the child’s didMoveToParentViewController: method to signal that the operation is complete.

Eventually, you want to be able to remove the child’s view from the view hierarchy. In this case, shown in Listing 14-2, you perform the steps in reverse.


----------

2.Removing another view controller’s view to the container’s view hierarchy

- (void) hideContentController: (UIViewController*) content

{

[content willMoveToParentViewController:nil];? // 1

[content.view removeFromSuperview];? ? ? ? ? ? // 2

[content removeFromParentViewController];? ? ? // 3

}

Here’s what this code does:

Calls the child’s willMoveToParentViewController: method with a parameter of nil to tell the child that it is being removed.

Cleans up the view hierarchy.

Calls the child’s removeFromParentViewController method to remove it from the container. Calling the removeFromParentViewController method automatically calls the child’s didMoveToParentViewController: method.

For a container with essentially static content, adding and removing view controllers is as simple as that. Whenever you want to add a new view, add the new view controller as a child first. After the view is removed, remove the child from the container. However, sometimes you want to animate a new child onto the screen while simultaneously removing another child. Listing 14-3 shows an example of how to do this.

----------

3.Transitioning between two view controllers

- (void) cycleFromViewController: (UIViewController*) oldC

toViewController: (UIViewController*) newC

{

[oldC willMoveToParentViewController:nil];? ? ? ? ? ? ? ? ? ? ? ? // 1

[self addChildViewController:newC];

newC.view.frame = [self newViewStartFrame];? ? ? ? ? ? ? ? ? ? ? // 2

CGRect endFrame = [self oldViewEndFrame];

[self transitionFromViewController: oldC toViewController: newC? // 3

duration: 0.25 options:0

animations:^{

newC.view.frame = oldC.view.frame;? ? ? ? ? ? ? ? ? ? ? // 4

oldC.view.frame = endFrame;

}

completion:^(BOOL finished) {

[oldC removeFromParentViewController];? ? ? ? ? ? ? ? ? // 5

[newC didMoveToParentViewController:self];

}];

}

Here’s what this code does:

Starts both view controller transitions.

Calculates two new frame positions used to perform the transition animation.

Calls the transitionFromViewController:toViewController:duration:options:animations:completion: method to perform the swap. This method automatically adds the new view, performs the animation, and then removes the old view.

The animation step to perform to get the views swapped.

When the transition completes, the view hierarchy is in its final state, so it finishes the operation by sending the final two notifications.

--------------------------------------------

要開始耍啦啦啦播急。。售睹。


?在.h文件中桩警,留下一些外部訪問的屬性和方法:

@property (nonatomic, copy, readonly) NSArray * viewControllers;

@property (nonatomic, copy, readonly) NSArray * barItemImages;

- (instancetype)initWithViewControllers:(NSArray *)viewControllers barItemImages:(NSArray *)barItemImages;

- (instancetype)initWithViewControllers:(NSArray *)viewControllers;


在.m文件中 首先會定義一些屬性:

#import "DHTabViewController.h"


typedef NS_ENUM(NSUInteger, ViewTag) {

ButtonTag = 100

};

@interface DHTabViewController ()

@property (nonatomic, copy) NSArray * viewControllers;

@property (nonatomic, copy) NSArray * barItemImages;

@property (nonatomic, assign) NSUInteger selectedControllerIndex;

@property (nonatomic, strong) UIView * buttonContainerView;

@property (nonatomic, strong) UIView * childControllerContainerView;

- (void)initializeAppearance;

@end

--------------------------------------------

說明一下,我們應(yīng)該遵循一定的代碼規(guī)范(叫嗎昌妹?我也不知道捶枢。。)

#init

#life circle

#system delegate

#custom delegate?

#private method

#getter setter

就是關(guān)于各種方法位置的順序啦飞崖。烂叔。

--------------------------------------------

@implementation DHTabViewController

#pragma mark - initializer

- (instancetype)initWithViewControllers:(NSArray *)viewControllers

{

self = [self initWithViewControllers:viewControllers barItemImages:@[]];

return self;

}

- (instancetype)initWithViewControllers:(NSArray *)viewControllers barItemImages:(NSArray *)barItemImages

{

self = [super init];

if (self) {

self.selectedControllerIndex = 0;

self.viewControllers = viewControllers;

self.barItemImages = barItemImages;

}

return self;

}

- (instancetype)init

{

self = [self initWithViewControllers:@[]];

return self;

}


pragma mark - 生命周期

- (void)viewDidLoad {

[super viewDidLoad];

[self initializeAppearance];

}

#pragma mark - action/callback

- (void)action_onButton:(UIButton *)sender

{

NSUInteger index = sender.tag - ButtonTag;

if (index == self.selectedControllerIndex) {

return;

}

// 移除當(dāng)前顯示的controller

UIViewController * currentController = self.viewControllers[self.selectedControllerIndex];

[currentController.view removeFromSuperview];

[currentController removeFromParentViewController];

[currentController willMoveToParentViewController:nil];

// 加載選擇的controller

UIViewController * selectedController = self.viewControllers[index];

[self addChildViewController:selectedController];

self.selectedControllerIndex = index;

}

#pragma mark - system protocol implentations

#pragma mark - custom protocol implentations

#pragma mark - private methods

- (void)initializeAppearance

{

if (self.viewControllers.count == 0) {

return;

}

[self.view addSubview:self.childControllerContainerView];

[self.view addSubview:self.buttonContainerView];

// 默認(rèn)加載第一個controller的內(nèi)容

UIViewController * firstViewController = self.viewControllers.firstObject;

[self addChildViewController:firstViewController];

// 初始化切換controller的按鈕

CGFloat buttonWidth = CGRectGetWidth(self.view.bounds) / self.viewControllers.count;

[self.viewControllers enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

UIButton * button = [UIButton buttonWithType:UIButtonTypeSystem];

[button setBackgroundColor:[UIColor yellowColor]];

[button addTarget:self action:@selector(action_onButton:) forControlEvents:UIControlEventTouchUpInside];

[button setFrame:CGRectMake(idx * buttonWidth, 0, buttonWidth, 40)];

if (self.barItemImages.count > 0) {

[button setImage:self.barItemImages[idx] forState:UIControlStateNormal];

} else {

[button setTitle:[NSString stringWithFormat:@"%ld",idx+1] forState:UIControlStateNormal];

}

button.tag = ButtonTag+idx;

[self.buttonContainerView addSubview:button];

}];

}

#pragma mark - override

- (void)addChildViewController:(UIViewController *)childController

{

[self.childControllerContainerView addSubview:childController.view];

childController.view.frame = CGRectOffset(self.view.frame, 0, 40);

[super addChildViewController:childController];

[childController didMoveToParentViewController:self];

}

#pragma mark - getter

- (UIView *)buttonContainerView

{

if (!_buttonContainerView) {

_buttonContainerView = ({

UIView * view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 40)];

[self childControllerContainerView];

view;

});

}

return _buttonContainerView;

}

- (UIView *)childControllerContainerView

{

if (!_childControllerContainerView) {

_childControllerContainerView = ({

UIView * view = [[UIView alloc] initWithFrame:self.view.bounds];

[self buttonContainerView];

view;

});

}

return _childControllerContainerView;

}

@end


懶得翻譯了。固歪。都是很簡單的單詞蒜鸡,大家理解的哈

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市牢裳,隨后出現(xiàn)的幾起案子逢防,更是在濱河造成了極大的恐慌,老刑警劉巖贰健,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件胞四,死亡現(xiàn)場離奇詭異,居然都是意外死亡伶椿,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進(jìn)店門氓侧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來脊另,“玉大人,你說我怎么就攤上這事约巷≠送矗” “怎么了?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵独郎,是天一觀的道長踩麦。 經(jīng)常有香客問我,道長氓癌,這世上最難降的妖魔是什么谓谦? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮贪婉,結(jié)果婚禮上反粥,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好才顿,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布莫湘。 她就那樣靜靜地躺著,像睡著了一般郑气。 火紅的嫁衣襯著肌膚如雪幅垮。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天尾组,我揣著相機(jī)與錄音军洼,去河邊找鬼。 笑死演怎,一個胖子當(dāng)著我的面吹牛匕争,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播爷耀,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼甘桑,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了歹叮?” 一聲冷哼從身側(cè)響起跑杭,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎咆耿,沒想到半個月后德谅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡萨螺,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年窄做,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片慰技。...
    茶點(diǎn)故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡椭盏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出吻商,到底是詐尸還是另有隱情掏颊,我是刑警寧澤,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布艾帐,位于F島的核電站乌叶,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏柒爸。R本人自食惡果不足惜准浴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望揍鸟。 院中可真熱鬧兄裂,春花似錦句旱、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至匾南,卻和暖如春啃匿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蛆楞。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工溯乒, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人豹爹。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓裆悄,卻偏偏與公主長得像,于是被迫代替她去往敵國和親臂聋。 傳聞我的和親對象是個殘疾皇子光稼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評論 2 359

推薦閱讀更多精彩內(nèi)容

  • ViewsBecause view objects are the main way your applicati...
    梁光飛閱讀 606評論 0 0
  • /* UIViewController is a generic controller base class th...
    DanDanC閱讀 1,816評論 0 2
  • 我們大多數(shù)情況都會使用NavigationController和 TabbarController去管理自己的VC...
    純情_小火雞閱讀 227評論 0 0
  • **2014真題Directions:Read the following text. Choose the be...
    又是夜半驚坐起閱讀 9,573評論 0 23
  • 漫長四+年,我們的臉上刻盡了歲月的滄桑孩等,發(fā)間染上了點(diǎn)點(diǎn)秋霜艾君,再也找不到青春的時光,只能在兒孫們的身上看到過去的影子...
    寧寧姥爺閱讀 191評論 1 1