iOS开发:第一个iOS程序分析——AppDelegate.h文件和视图View、视图控制器ViewController

摘要:
在上一篇文章中,iOS开发:第一个iOS程序分析-代理,生命周期功能主要介绍了两个主要文件。m和AppDelegate。m由iOS使用Objective-C开发,并具有控制程序生命周期的功能。接下来,我们将介绍另外两个文件:AppDelegate。h文件,UIViewController。m文件以及iOS开发中的View和ViewController。了解了这一点,就不难理解为什么KZXAppDelegate类中有对UIWindow的引用。视图级别的最高级别是窗口对象。

上一篇文章iOS开发:第一个iOS程序分析——代理,生命周期函数中主要介绍了iOS使用Objective-C开发的两个主要文件main.m和AppDelegate.m和控制程序生命周期的函数,接下来将介绍另外两个文件:AppDelegate.h文件、UIViewController.m文件和iOS开发中的View和ViewController。

打开AppDelegate.h文件:

先看一下AppDelegate类,前面说过,AppDelegate是作为Application的代理,这个程序中的AppDelegate不仅负责控制程序的生命周期,而且负责控制程序初始界面(初始StoryBoard)的显示,因此该代理类必须能够访问到初始界面的界面元素。

明白这点,就不难了解KZX AppDelegate类中为什么会有UIWindow的一个引用了。如下

该文件只有以下寥寥几行代码:

<span style="font-family:Comic Sans MS;font-size:14px;">#import <UIKit/UIKit.h>

@interface KZXAppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@end
</span>

除去导入头文件的语句,文件由@interface开始声明到@end结束声明,可以看到,确实该代理类持有一个UIWindow类的实例,该UIWindow实例即代表了该视图控制器所负责控制显示的窗口视图(即一个屏幕界面),读者朋友可以尝试把这一句删去,会发现运行程序后是黑漆漆一片,因为代理无法找到应该在哪里显示视图。自然没有界面。

那么为什么代理要持有UIWindow的实例而不持有其他视图的实例呢?

先来看看官方文档对于视图的说明(View):

“Views not only display themselves onscreen and react to user input, they also serve as containers for other views. As a result, views in an app are arranged in a hierarchical structure called the view hierarchy. The view hierarchy defines the layout of views relative to other views. Within that hierarchy, view instances enclosed within a view are called subviews, and the parent view that encloses a view is referred to as its superview. Even though a view instance can have multiple subviews, it can have only one superview.At the top of the view hierarchy is the window object. ”

"视图不仅在屏幕上显示他们本身、对用户的输入做出反应,而且也能够作为容器来为其他视图提供服务。所以一个app中的视图是被组织成一种层次结构的,叫做视图层级。视图层级决定了不同但是相关的视图之间的布局和排版。在视图层级里面,多个视图围绕某个特定的视图来布局,则该特定的视图称为父视图,而围绕父视图布局的其他视图称为子视图。尽管一个视图能够拥有多个子视图但是一个视图不可能有多个父视图。在视图层级的最高层次是window对象"。

注意最重要的是最后一句话,也就是说如果把视图层级看成一棵树的话,那么这棵树的根就是window对象,因此学过树数据结构的都知道,持有根节点当然能方便地访问其他所有节点,这就是AppDelegate持有UIWindow的原因。


注意到@interface AppDelegate后还带了: UIResponder <UIApplicationDelegate>,在Objective-C中,继承写法跟C++一样都是用冒号(半角)来表示,所以这一句表示了该代理类继承了UIResponder类,但是后半部分<UIApplicationDelegate>则体现了Objective-C还有的 协议 这种概念,协议类似于Java中的接口,与接口不同的是实现协议可以不实现协议的所有方法,具体要看协议声明方法时是用@optional还是@required。可在Xcode中command+点击UIApplicationDelegate看看,如下。

<span style="font-family:Comic Sans MS;font-size:14px;">@protocol UIApplicationDelegate<NSObject>

@optional

- (void)applicationDidFinishLaunching:(UIApplication *)application;
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions NS_AVAILABLE_IOS(6_0);
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions NS_AVAILABLE_IOS(3_0);

- (void)applicationDidBecomeActive:(UIApplication *)application;
- (void)applicationWillResignActive:(UIApplication *)application;
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url;  // Will be deprecated at some point, please replace with application:openURL:sourceApplication:annotation:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation NS_AVAILABLE_IOS(4_2); // no equiv. notification. return NO if the application can't open for some reason

- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application;      // try to clean up as much memory as possible. next step is to terminate app
- (void)applicationWillTerminate:(UIApplication *)application;
- (void)applicationSignificantTimeChange:(UIApplication *)application;        // midnight, carrier time update, daylight savings time change

- (void)application:(UIApplication *)application willChangeStatusBarOrientation:(UIInterfaceOrientation)newStatusBarOrientation duration:(NSTimeInterval)duration;
- (void)application:(UIApplication *)application didChangeStatusBarOrientation:(UIInterfaceOrientation)oldStatusBarOrientation;

- (void)application:(UIApplication *)application willChangeStatusBarFrame:(CGRect)newStatusBarFrame;   // in screen coordinates
- (void)application:(UIApplication *)application didChangeStatusBarFrame:(CGRect)oldStatusBarFrame;
</span>


...省略若干行


接下来就是KZXViewController.m(KZXViewController.h几乎没有内容):

先来看看Apple对视图控制器的一些官方文档(ViewController):

“In an iOS app, you use a view controller (UIViewController) to 

manage a content view with its hierarchy of subviews.A view 

controller isn’t part of the view hierarchy and it’s not an element 

in your interface. Instead, it manages the view objects in the hierarchy

and provides them with behavior.
You also use view controllers to implement transitions from one type of 

content to another. Because iOS apps have a limited amount of space in 

which to display content, view controllers provide the infrastructure 

needed to remove the views of one view controller and replace them 

with the views of another.”


在一个iOS 的 app 中,你使用一个视图控制器(UIViewController)来

管理一个具有内容的视图以及他的子视图层级。注意视图控制器并不是视

图层级的一部分,而且也不属于用户界面的元素。实际上,他是用来管理

视图层级中的视图对象的,并且为他们定义一些响应行为(来作为与用户

的交互)。当然也可以使用视图控制器来作为两个(种)具有内容的视图

的过渡,毕竟iOS app(实际上应该是iOS的大部分设备屏幕)只有有限的

空间来显示内容,视图控制器提供了删除视图和替换视图的一些必须的基础函数。“


由以上可知,一个视图的视图控制器实际负责两部分——管理该视图的

子视图层级,管理该视图与其他视图的转换。

回到KZXViewController.m文件,该文件中定义了如下函数:

<span style="font-family:Comic Sans MS;font-size:14px;">- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

- (void)viewDidLoad

- (void)didReceiveMemoryWarning

</span>

initWithNibName使用一个xib文件名(视图布局文件)来初始化视图

的子视图层级,viewDidLoad在初始化完毕后调用(两个函数对应“管理

子视图层级”功能),而didReceiveMemoryWarning通常在内存不足时

被警告时调用,此函数一般用来释放一些资源和数据。

关于体现视图控制器“管理该视图与其他视图转换”的功能,

读者朋友可以打开UIViewController头文件看声明的方法对应。


总结:

1.代理通过适时调用委托方的函数来控制对委托方的访问,ApplicationDelegate

作为整个app的代理不仅要控制app的生命周期,还要负责app入口界面,因此

ApplicationDelegate持有app入口界面的视图层级根视图——UIWindow。

2.视图控制器负责管理该视图的子视图层级以及管理该视图与其他视图的转换。

视图控制器不属于视图,不在视图层级之内。


下一次我们将介绍MainStoryBoard.storyboard文件以及常用的一些视图控件的使用。


免责声明:文章转载自《iOS开发:第一个iOS程序分析——AppDelegate.h文件和视图View、视图控制器ViewController》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇git flow常用命令用广播监听安卓设备电量状态下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

iOS开发 字符串

iOS开发之玩转字符串 (转)这是另一个收藏的超链接 来自SegmentFault 大神的精品 下面这是一些常用的方法和属性 记得不牢所以收藏下 //一、NSString /*----------------创建字符串的方法----------------*///1、创建常量字符串。NSString *astring = @"This is a Strin...

iOS开发语法篇block详解

一:基本定义 /*初步上式block定义的一些理解和解释,接下来会详解: *block名为myBlock,结合C的函数指针,myBlock为block体的指针,指向block体的入口地址 *int result = myBlock(5) <==> ^(int num){return num*num}(5)//将5传给num *回调时可以将my...

Windows上实现iOS APP自动化测试:tidevice + WDA + facebook-wda / appium

本文介绍如何在Windows下构建iOS APP自动化测试环境,采用的主要工具为tidevice,WebDriverAgent,facebook-wda或者appium。 目录 测试架构介绍 WebDriverAgent原理分析 tidevice原理分析 iOS 设备安装 wda 1、安装Xcode 2、下载WebDriverAgent 3、...

iOS开发-Runloop详解(简书)

不知道大家有没有想过这个问题,一个应用开始运行以后放在那里,如果不对它进行任何操作,这个应用就像静止了一样,不会自发的有任何动作发生,但是如果我们点击界面上的一个按钮,这个时候就会有对应的按钮响应事件发生。给我们的感觉就像应用一直处于随时待命的状态,在没人操作的时候它一直在休息,在让它干活的时候,它就能立刻响应。其实,这就是run loop的功劳。 一、线...

iOS开发UI篇—iOS开发中Xcode的一些使用技巧

一、快捷键的使用 经常用到的快捷键如下: 新建 shift + cmd + n 新建项目 cmd + n 新建文件 视图 option + cmd + 回车 打开助理编辑器 cmd + 回车 显示主窗口 cmd +0 导航窗口 option + cmd +0 工具窗口 在.m & .h之间切换 control + cmd + 上/下 按照浏览文件的...

【转】IOS开发—IOS 8 中设置applicationIconBadgeNumber和消息推送

 在IOS7中设置applicationIconBadgeNumber不会有什么问题,但是直接在IOS8中设置applicationIconBadgeNumber会报错 因为在IOS8中要想设置applicationIconBadgeNumber,需要用户的授权,在IOS8中,需要加上下面的代码: ? 1 2 UIUserNotificatio...