内容简介:竖屏模式的记事本.png为了实现这个功能,我开发了一个记事本类的视图控制器NotepadViewController,然后把NotepadViewController的View作为subview添加到mainview。
1.对addChildViewController的一点理解
参考: stackoverflow
-
这一切都取决于你想要怎样管理你的子视图,如果你的子视图只是UIVIew,比如一些Button,label之类的,那么使用addsubview就好了。但是。如果你的子视图是由自己的UIViewController来管理的,即它有足够复杂的视图集合,丰富的功能,那么你就调用addChildViewController来添加新的视图控制器,但是记住,addsubview也是需要的。
-
在以前,一个UIViewController的View可能有很多的小的子View,这些View很多时候都是被盖在最后,而没有显示出来。我们在UIViewController的viewdidload方法中用addsubview增加了大量的子View。这些子View不会一直处于界面上,而是在特定的时间出现,比如登录失败的提示View,上传附件成功的提示View,网络失败的提示View等。这些View虽然很少出现,但是我们却常常一直把它放在内存中,出现内存警告时只好手动把它们从superview移除。
-
现在苹果建议我们当我们的子View有单独的viewcontroller管理时,在添加子View时顺带使用addchildViewcontroller把管理该视图的视图控制器作为子控制器添加进来。并且当我们暂时不需要显示这个子视图时可以只执行addchildViewController操作,而不执行addsubview操作,当需要显示时再调用transitionFromViewController:toViewController:duration:options:animations:completion 方法将子视图显示出来。
另外,当收到系统的 Memory Warning 的时候,系统也会自动把当前没有显示的 subview unload 掉,以节省内存。
2 addChildViewController到底做了什么
借用stackoverflow上面的一个例子来看看addchildViewcontroller到底做了什么。
现在正在开发一个图书馆的APP,当想要做笔记时出现一个记事本视图,像下面这样:
竖屏模式的记事本.png
为了实现这个功能,我开发了一个记事本类的视图控制器NotepadViewController,然后把NotepadViewController的View作为subview添加到mainview。
这样看来是不是一切完美,那么当我们旋转屏幕呢?
横屏模式的记事本.png
糟了,我们发现记事本View的下面有一部分被键盘遮住了。
怎么办呢?我们想到在旋转屏幕的时候把NotepadViewController的View往上移动一点点,这样记事本视图就不会被遮住了。因此我们在NotepadViewController.m中实现willAnimateRotationToInterfaceOrientation:duration:方法把视图往上移动一点。但是当我们运行APP的时候就发现NotepadViewController.m中和旋转相关的方法压根就没有被调用,只是mainview的viewcontroller的相关的旋转方法被调用了。
为了解决这个问题,我们只好在mainviewcontroller中手动调用NotepadViewController.m中相关的方法,这样会使事情变得复杂起来并且不相关的组件之间产生耦合。
-
但是现在那些困扰都已经成为了过去式,只是因为有了addchildviewcontroller这个方法。当我们调用addchildviewcontroller把NotepadViewController添加到mainviewcontroller后,在屏幕发生旋转时,在NotepadViewController.m中也会调用willAnimateRotationToInterfaceOrientation:duration:方法。
如果你去测试,你会发现,如果只是使用addsubview方法,那么在APP启动时并不会调用子视图控制器的viewWillAppear:方法。但是如果我们把该子视图控制器作为子视图调用addchildviewcontroller添加进mainviewcontroller时,viewWillAppear就会调用了。
-
结论
有两类事件会被转发给子视图控制器:
1-外观方法:
- viewWillAppear: - viewDidAppear: - viewWillDisappear: - viewDidDisappear:
2-旋转方法:
- willRotateToInterfaceOrientation:duration:- willAnimateRotationToInterfaceOrientation:duration:- didRotateFromInterfaceOrientation:
3 一个小Demo
addcchildviewcontroller更多的是用在容器类的视图控制器中。比如说现在很多新闻类的APP的标签栏有很多的标签,点击一个标签就会进入一个视图控制器的View。
下面就来模仿一下网易新闻的这个标签栏的设计。主要讲解都在代码中。
#import "MainViewController.h"#import "FirstViewController.h"#import "SecondViewController.h"#import "ThirdViewController.h"@interface MainViewController ()@property (nonatomic, strong)UIScrollView *headerScrollView;//滚动的顶部视图@property (nonatomic, strong)NSArray *headerArray;@property (nonatomic, strong)FirstViewController *firstVC;@property (nonatomic, strong)SecondViewController *secondVC;@property (nonatomic, strong)ThirdViewController *thirdVC;@property (nonatomic, strong)UIViewController *currentViewController;@end@implementation MainViewController- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = @"网易新闻Demo";
self.headerArray = @[@"头条",@"娱乐",@"体育",@"财经",@"科技",@"NBA",@"手机"];
_headerScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 64, 375, 40)];
_headerScrollView.contentSize = CGSizeMake(525, 0);
_headerScrollView.pagingEnabled = YES;
_headerScrollView.showsHorizontalScrollIndicator = NO;
[self.view addSubview:_headerScrollView];
for(int i = 0; i < _headerArray.count; i++){
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(75*i, 0, 75, 40)];
button.backgroundColor = [UIColor grayColor];
[button setTitle:_headerArray[i] forState:UIControlStateNormal];
button.tag = 100 + i;
[button addTarget:self action:@selector(headerButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
[_headerScrollView addSubview:button];
}
_firstVC = [[FirstViewController alloc] init];
[_firstVC.view setFrame:CGRectMake(0, 104, 375, 563)];
[self.view addSubview:_firstVC.view];//默认是第一个视图
/*
苹果新的API增加了addChildViewController方法,并且希望我们在使用addSubview时,同时调用[self addChildViewController:child]方法将sub view对应的viewController也加到当前ViewController的管理中。
对于那些当前暂时不需要显示的subview,只通过addChildViewController把subViewController加进去;需要显示时再调用transitionFromViewController方法。将其添加进入底层的ViewController中。
这样做的好处:
1.无疑,对页面中的逻辑更加分明了。相应的View对应相应的ViewController。
2.当某个子View没有显示时,将不会被Load,减少了内存的使用。
3.当内存紧张时,没有Load的View将被首先释放,优化了程序的内存释放机制。
*/
/**
* 在iOS5中,ViewController中新添加了下面几个方法:
* addChildViewController:
* removeFromParentViewController
* transitionFromViewController:toViewController:duration:options:animations:completion:
* willMoveToParentViewController:
* didMoveToParentViewController:
*/
[self addChildViewController:_firstVC];
_currentViewController = _firstVC;
_secondVC = [[SecondViewController alloc] init];
[_secondVC.view setFrame:CGRectMake(0, 104, 375, 563)];
_thirdVC = [[ThirdViewController alloc] init];
[_thirdVC.view setFrame:CGRectMake(0, 104, 375, 563)];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}
- (void)headerButtonClicked:(UIButton *)button{ //点击的是当前的页面时,直接返回,什么也不做呢
if((self.currentViewController == _firstVC&&button.tag == 100)||(self.currentViewController == _secondVC&&button.tag == 101)||(self.currentViewController == _thirdVC&&button.tag == 102)){
return ;
}
switch (button.tag) { case 100:
[self presentFormOldViewController:_currentViewController toNewViewController:_firstVC]; break; case 101:
[self presentFormOldViewController:_currentViewController toNewViewController:_secondVC];
break; case 102:
[self presentFormOldViewController:_currentViewController toNewViewController:_thirdVC]; break; default: break;
}
}
- (void)presentFormOldViewController:(UIViewController *)oldController toNewViewController:(UIViewController *)newController{
/**
* 着重介绍一下它
* transitionFromViewController:toViewController:duration:options:animations:completion:
* fromViewController 当前显示在父视图控制器中的子视图控制器
* toViewController 将要显示的姿势图控制器
* duration 动画时间(这个属性,old friend 了 O(∩_∩)O)
* options 动画效果(渐变,从下往上等等,具体查看API)
* animations 转换过程中得动画
* completion 转换完成
*/
[self addChildViewController:newController];
[self transitionFromViewController:_currentViewController toViewController:newController duration:10.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
} completion:^(BOOL finished) {
if(finished){
[oldController removeFromParentViewController]; self.currentViewController = newController;
}else{ self.currentViewController = oldController;
}
}];
}@end
作者:雪山飞狐_91ae
链接:https://www.jianshu.com/p/0d81ba13af37
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 理解原型其实是理解原型链
- 要理解深度学习,必须突破常规视角去理解优化
- 深入理解java虚拟机(1) -- 理解HotSpot内存区域
- 荐 【C++100问】深入理解理解顶层const和底层const
- 深入理解 HTTPS
- 深入理解 HTTPS
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
How to Solve It
Zbigniew Michalewicz、David B. Fogel / Springer / 2004-03-01 / USD 59.95
This book is the only source that provides comprehensive, current, and detailed information on problem solving using modern heuristics. It covers classic methods of optimization, including dynamic pro......一起来看看 《How to Solve It》 这本书的介绍吧!