您的当前位置:首页正文

《View Controller Programming Gui

来源:图艺博知识网

简写:
vc = viewcontroller
app = application
delegate

vc的角色

vc最重要角色是管理所有view,每个vc有个根view(root view),所有其他view都在根view上。vc强引用root view,rootview强引用其他子view。

vc的角色 container

vc作为数据和view之间的中转,应该做好自己的角色定位,不做数据的处理,数据应该由自己处理相应的逻辑。

每个window有个root vc,vc的内容充满window。如果是自己建立的window,需要设置一下root vc。

presented vc通常用于展示与之前vc内容逻辑上不成一体的内容。Presenting一个vc将会用新视图替换原来的vc的内容(通常隐藏之前vc内容),例如present一个vc用于输入内容。当present一个vc时,UIKit会自动创建好presented vc和presenting vc的链。当container vc被需要时,UIKit可能会改变之前的链以简化代码,例如下图:导航vc上已经存在一个子vc,当presente一个全屏vc时,不需要子vc上面present,而是通过导航vc直接present,因为导航vc本身就是铺满屏幕的vc。
When you present a view controller, UIKit looks for a view controller that provides a suitable context for the presentation. In many cases, UIKit chooses the nearest container view controller but it might also choose the window’s root view controller. In some cases, you can also tell UIKit which view controller defines the presentation context and should handle the presentation.

系统根据上下文选择可以present的父vc--通常是最近的container vc或者rootvc。

presente

container vc添加子vc:其中addChildViewController会自动调用子vc的代理方法willMoveToParentViewController,然后需要调整子vc的根view的frame保证其正确显示,然后将其加入到container vc的root view上,最后调用didMoveToParentViewController方法通知子vc,因为这个不会自动调用。

- (void)displayContentController:(UIViewController*)content
{
    [selfaddChildViewController:content];
    content.view.frame=[selfframeForContentController];
    [self.viewaddSubview:self.currentClientView];
    [contentdidMoveToParentViewController:self];
}
- (void)hideContentController:(UIViewController*)content
{
    [contentwillMoveToParentViewController:nil];
    [content.viewremoveFromSuperview];
    [contentremoveFromParentViewController];
}

当你想要动画化子vc之间的互换,你可以将子vc的添加和移除操作放到过渡动画的过程中来模拟。

- (void)cycleFromViewController:(UIViewController*)oldVC
toViewController:(UIViewController*)newVC
{
    // Prepare the two view controllers for the change. 让子vc知道即将移除
    [oldVCwillMoveToParentViewController:nil];
    [selfaddChildViewController:newVC];
    // Get the start frame of the new view controller and the end frame
    // for the old view controller. Both rectangles are offscreen.
    newVC.view.frame=[selfnewViewStartFrame];
    CGRectendFrame=[selfoldViewEndFrame];
    // Queue up the transition animation.transitionFromViewController自动更新vc中view的层次
    [selftransitionFromViewController:oldVCtoViewController:newVC duration:0.25options:0 animations:^{
    // Animate the views to their final positions.新vc view入位,老vc的view移除
        newVC.view.frame=oldVC.view.frame;
        oldVC.view.frame=endFrame;
    }
    completion:^(BOOLfinished){
    // Remove the old view controller and send the final
    // notification to the new view controller. 移除老vc,通知新vc已添加
        [oldVCremoveFromParentViewController];
        [newVCdidMoveToParentViewController:self];
    }];
}

管理子vc的出现进程:添加子vc到container上后,container自动将相关消息转发给子vc。但如果多个子vc并发改变view的状态,相应的事件并非按照逻辑顺序。处理这种情况,可以实现代码里方法返回no,让系统不要自动转发这些消息:

- (BOOL)shouldAutomaticallyForwardAppearanceMethods
{
    returnNO;
}

系统不自动转发,我们就需要自己来通知子vc:

- (void)viewWillAppear:(BOOL)animated
{
    [self.childbeginAppearanceTransition:YESanimated:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
    [self.childendAppearanceTransition];
}
- (void)viewWillDisappear:(BOOL)animated
{
    [self.childbeginAppearanceTransition:NOanimated:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
    [self.childendAppearanceTransition];
}

container需要注意只访问子vc的root view,不要干涉其他view; container定义一些协议方法,让子vc通过这些方法来与container沟通,以保证子vc对container干涉最小。

vc的可理解性支持

可理解性支持:一个好的app需要充分考虑弱视等有部分身体缺陷用户的正常使用,需要考虑在合适位置安排VoiceOver(系统提供的屏幕阅读辅助工具),暂略。

vc的保存和恢复

vc的保存和恢复需要:

  1. 需要保存的vc赋值一个恢复id
  2. 告知系统在app启动时如何恢复创建和定位新vc
    赋值id:标记vc:对vc的属性赋值一个字符串,注意所有父vc都需要赋值。在app启动时,系统会从window的root vc开始遍历vc的层次,逐个恢复,如果某个vc没有id,它和它所有子vc将无法恢复。 如果系统无法自动创建恢复vc,将会通知app创建,并提供所有相关的父与子,其实对应的就是一个重建路径。所以最好是唯一的并且可辨识,可以为类名。如果想排除一组vc,只需要将父vc的设置nil。
    注意:排除vc自动保存后,app启动后如果vc在相关的恢复过程中(vc与要恢复的其他vc有关),这个vc也会被app重建,只是以默认的配置重建。
    对于vc上view如果想保存状态,也需要赋值,如果是table或collection需要遵循协议。

app启动时,系统按下面顺序呢恢复vc:

  1. 如果vc有恢复类,使用这个类调用来恢复vc;
  2. 否则使用app delegate恢复vc:调用
  3. 如果存在重建路径,则通过这个路径重建。
  4. 如果是storyboard,通过保存的storyboard新来重建

present vc

1.全屏
全屏present模式
2.popover:
popover
3.当前上下文
UIModalPresentationCurrentContext
4.自定义
过渡

Dismiss

Segue

storyboard直接拉线起点必须是相应用户操作的view或者手势等类型,可以设置segue的显示类型,如push、modal、popover等。过程如下:

流程
其中给用户判断是否要跳转到对应界面;负责传递数据。
当vc需要dismiss时,只需把segue的线连接到 storyboard上面的 exit。
自定义segue:
子类化UIStoryboardSegue,实现initWithIdentifier:source:destination:
Top