iOS学习5_控制器的创建方式和控制器view的创建

UIScreen是与设备有关的物理屏幕

Window是一个窗口对应UIWindow类,继承自UIView,window要显示在Screen上必须设置为主窗口并且可见。接下来就可以往UIWindow上面添加一些控件了。

下图就是简单地层次关系

ViewController是用来组织和控制视图的,与上图不同的是这里使用了视图控制器ViewController,不需要直接将view指定给window,相反,只需要给window制定一个视图控制器,视图控制器会自动的将他的view添加给window。如下图所示:

引入控制器有点像Android里面的Activity。


UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
levelViewController = [[LevelViewController alloc] init];
window.rootViewController = levelViewController;
// 类似于下面这句
//[window addSubView: levelViewController.view];
[window makeKeyAndVisible];

创建控制器的三种方式

1.通过storyboardd

iOS会自动的执行下面的操作

实例化一个window

加载主storyboard并且实例化初始ViewController

指定视图控制器为window的根控制器rootViewController,接下来使得window显示在屏幕上

使用代码描述大概:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    QHViewController * vc = [storyboard instantiateInitialViewController];
    self.window.rootViewController = vc;
    [self.window makeKeyAndVisible];
    return YES;
}

注意:以上三个步骤是iOS主动做的,因此建立singleView的项目会看不到application:didFinishLaunchingWithOptions:方法里面有任何内容。

要想自己使用storyboard里面的其他控制器需要通过UIStoryBoard对象来实现

a.      通过UIStoryboard类的storyboardWithName方法得到UIStoryBoard对象

b.      通过instantiateInitialViewController或者instantiateViewControllerWithIdentifier:方法得到对应的控制器

代码大致如下:

UIStoryboard *storyboard = self.storyboard;
    SpecialViewController *svc = [storyboard instantiateViewControllerWithIdentifier:@"SpecialViewController"];

    // Configure the new view controller here.

    [self presentViewController:svc animated:YES completion:nil];

2.使用xib

Xib是storyboard的前身,使用storyboard的好处是可以建立起界面跳转的关系,看起来更加直观。

创建一个继承自UIViewController的类。创建一个xib文件,将其File’s owner指定为自定义的控制器,并且一定要将view属性连线到要显示的那个View里面(因为一个xib文件里面可能有多个UIView)

QHViewController *controller=[[ QHViewController alloc]initWithNibName:@"test" bundle:nil];

其实上面这句若写成了

QHViewController *controller=[[ QHViewController alloc]init];

也可以加载xib,只不过加载不了名字为text.xib的文件,后面会讲到。

可能的错误:

a. was unable to load a nib named XXX:说明xib里面没有任何view

b. loaded the XXX nib but the view outlet was not set :将其File’sowner指定为自定义的控制器,并且一定要将view属性连线到要显示的那个View里面

3.使用纯代码

- (void)applicationDidFinishLaunching:(UIApplication *)application {
   UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
   levelViewController = [[LevelViewController alloc] init];
   window.rootViewController = levelViewController;
   [window makeKeyAndVisible];
}

上面这句levelViewController = [[LevelViewController alloc] init];在创建自己的控制器的时候其实会做以下的处理(控制器里面的view属性):

a.默认会查找与控制器匹配的.xib文件,匹配的意思是如果该控制器类为QHFirstViewController,那么匹配的.xib文件为QHFirstView.xib

b.如果未找到,会查找和控制器同名的.xib文件

c.以上均未找到,就会创建一个空白的View将其赋值给控制器的view属性。

self.view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame]; 

控制器中View的创建方式

面的c步骤可以通过在viewDidLoad方法里面打印self.view是有值的看出来,创建该view是在loadView方法里面做的。当view需要被展示而它却是nil时,viewController会调用该方法。可以重写一下loadView方法,发现程序停在那里无法执行,原因就是父类会做加载view的操作,调用[super loadView]就可以。使用纯代码写布局的话就不需要调用[super loadView]了,因为该方法的父类中实现的无外乎是通过storyboard或者xib加载view,既然要使用代码自定义也就没必要从其他地方加载了。

事实上,通过storyboardxib也是在loadView方法里面加载的。loadView方法做的事情如下图所示



官方给的图相当的好,展示出了loadView方法所做的事,只是通过xib加载view没有展现在上面,并且官方的文档没有xib相关的内容取而代之的是storyboard,这与苹果推崇storyboard是一致的。

控制器加载View的步骤如下:

如果view在内存中,则直接加载。相反,如果不存在,则UIViewController调用loadView方法

loadView方法执行如下操作:

1.如果你重载了这个方法,则必须创建必要的view并且将一个非nil值传给UIViewController的view属性。

2.如果你没有重载这个函数,UIViewController会默认使用UIViewController的nibName和nibBundle属性尝试从nib文件加载view。如果没有找到nib文件,则ViewController会通过以下两个步骤找到与其关联的nib。

A 如果类名包含Controller,例如ViewController的类名是MyViewController,则查找是否存在MyView.nib;

B 找跟ViewController类名一样的文件,例如MyViewController,则查找是否存在MyViewController.nib。

如果没有可用的nib文件,那么它创建一个空的UIView作为它的view。

控制器被设为主storyboard的初始控制器,才会先去storyboard查找view,否则不会去storyboard查找。

原文地址:https://www.cnblogs.com/qhyuan1992/p/5385303.html