详解UIKit框架:它所定义的iOS主线程执行流程

  如果我们使用模板来新建一个project,比如Master Detail Application或者tabbed Application之类,那么Xcode将会为我们自动生成Main.storyboard文件,这样一来那些本来实在源代码中间中被定义的线程执行流程,现在全部在这个故事版文件中被定义了。用故事版当然有故事版的好处,只能用来定义的可视化元素现在允许程序员用可视化的方式来定义,不过对于并不是非常熟悉iOS编程的程序员来说,这种搭建UI的方式并不利于维护修改,因为程序员不容易看到线程的实际执行过程。

如果用代码的方式,程序员就可以看到什么时候线程创建了UIWindow的实例,并定义这个窗口要承载的界面元素,以及什么时候根据UIWindow实例中的代码和数据绘出图形。方法makeKeyAndVisible告诉了线程应该如何绘图。

主线程执行流程

iOS应用主线程执行流程如下图,方块代表了代码集合或者线程需要获得的其它资源,箭头方向代表了线程的转移方向。

上图就是主线程的声明周期。我们看看main函数:

#import <UIKit/UIKit.h>

#import "QSAppDelegate.h"

int main(int argc, char * argv[])
{
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

这是线程的入口,之后执行函数UIApplicationMain.

UIApplicationMain()

函数是初始化程序的核心,它接受4个参数。

int UIApplicationMain ( int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName );

argc和argv:

  来自于main()接受的两个参数;

第三个参数:

  主要类的名字(principal class name),必须是UIApplication或其子类的名字,这个类的一个实例引用了当前iPhone应用,定义了事件循环的代码。它会告诉线程去读info.plist文件获取配置信息,以及Main.storyboard;如果这个参数为nil,则默认为@"UIApplication";

第四个参数:

  代理类的名字(delegate class name),线程在内存中创建一个代理类的实例,定义一些处理与操作系统相关的事件的代码。

UIApplication类(由UIKit来定义)

UIApplication(或者其子类)的对象主要做下面几件事:
1)负责处理到来的用户事件,并分发事件消息到监听该消息的目标对象(sender, action)。
2)管理以及控制视图,包括呈现、控制行为、当前显示视图等。
3)该对象对应一个应用程序委托对象,当一些生命周期内重要事件(可以包括系统事件或者生命周期控制事件)发生时,应用程序通知该对象。例如,应用程序启动、内存不够了或者应用程序结束等,让这些事件发生时,应用程序委托去响应。

这个类中定义了很多有用的代码,可供线程执行。

1.设置icon上的数字图标
//设置主界面icon上的数字图标,在2.0中引进, 缺省为0
[UIApplication sharedApplication].applicationIconBadgeNumber = 4;
2.设置摇动手势的时候,是否支持redo,undo操作

//摇动手势,是否支持redo undo操作。3.0以后引进,缺省YES

[UIApplication sharedApplication].applicationSupportsShakeToEdit =YES;
3.判断程序运行状态
//判断程序运行状态,在2.0以后引入
if([UIApplication sharedApplication].applicationState ==UIApplicationStateInactive){
NSLog(@"程序在运行状态");
}
4.阻止屏幕变暗进入休眠状态
//阻止屏幕变暗,慎重使用,缺省为no 2.0
[UIApplication sharedApplication].idleTimerDisabled =YES;
慎重使用本功能,因为非常耗电。
5.显示联网状态
//显示联网标记 2.0
[UIApplication sharedApplication].networkActivityIndicatorVisible =YES;

6.在map上显示一个地址
NSString* addressText [email protected]"1 Infinite Loop, Cupertino, CA 95014";
// URL encode the spaces
addressText = [addressText stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
NSString* urlText = [NSString stringWithFormat:@"http://maps.google.com/maps?q=%@", addressText];

[[UIApplication sharedApplication]openURL:[NSURL URLWithString:urlText]];
7.发送电子邮件
NSString *recipients [email protected]"mailto:[email protected][email protected],[email protected]&subject=Hello from California!";
NSString *body [email protected]"&body=It is raining in sunny California!";
NSString *email = [NSString stringWithFormat:@"%@%@", recipients, body];
email = [email stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

[[UIApplication sharedApplication]openURL:[NSURL URLWithString:email]];
8.打电话到一个号码
// Call Google 411
[[UIApplication sharedApplication]openURL:[NSURL URLWithString:@"tel://8004664411"]];
9.发送短信
// Text to Google SMS
[[UIApplication sharedApplication]openURL:[NSURL URLWithString:@"sms://466453"]];
10.打开一个网址
// Lanuch any iPhone developers fav site
[[UIApplication sharedApplication]openURL:[NSURL URLWithString:@"http://itunesconnect.apple.com"]];

AppDelegate类(由程序员来定义)

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
当由于其它方法打开应用程序(如URL指定或者连接),通知委托启动完毕
- (void)applicationWillTerminate:(UIApplication *)application
通知委托,应用程序将在关闭 退出,请做一些清理工作。
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
通知委托,应用程序收到了为来自系统的内存不足警告。-(void)applicationSignificantTimeChange:(UIApplication *)application
通知委托系统时间发生改变(主要是指时间属性,而不是具体的时间值)
打开URL
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
打开指定的URL
控制状态栏方位变化
– application:willChangeStatusBarOrientation:duration:
设备方向将要发生改变
– application:didChangeStatusBarOrientation:
活动状态改变
- (void)applicationWillResignActive:(UIApplication *)application
通知委托应用程序将进入非活动状态,在此期间,应用程序不接收消息或事件。-(void)applicationDidBecomeActive:(UIApplication *)application
通知委托应用程序进入活动状态,请恢复数据

可以看到UIApplication的头文件实现
@interface UIApplication :UIResponder <UIActionSheetDelegate>{
@package
id<UIApplicationDelegate> _delegate ; //这就是应用程序委托。
NSTimer .......
}
因此,如果我们希望获得appdelegate实例,不必通过import类的方式,只需要:
UIApplicationDelegate* delegate = [[UIApplication sharedApplication] delegate];

用代码替换故事版

说了很多iOS程序执行的真正流程,我们来检验一下我们的理解吧。

假如你的工程类都是以TC开头。
1.import你的appdelegate类,并修改第四个参数如下:
UIApplicationMain(argc, argv, nil, NSStringFromClass([TCAppDelegate class]));
2.删除Main.storyboard文件
3.在工程的Info.plist文件中删除Main storyboard file base name

4、修改delegate类中定义的方法:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    UIViewController *webPageViewController = [[WebPageViewController alloc] init];
    UIViewController *personalViewController = [[PersonalViewController alloc]init];
    UIViewController *meViewController = [[MeViewController alloc]init];
    UINavigationController *personalNavigationController = [[UINavigationController alloc]init];
    personalNavigationController.viewControllers = [NSArray arrayWithObjects:personalViewController, nil];
    UINavigationController *meNavigationController = [[UINavigationController alloc]init];
    meNavigationController.viewControllers = [NSArray arrayWithObjects:meViewController, nil];
    _tabBarController = [[UITabBarController alloc]init];
    _tabBarController.viewControllers = [NSArray arrayWithObjects:webPageViewController, personalNavigationController, meNavigationController,nil];
    self.window.rootViewController = _tabBarController;

    _tabBarController.selectedIndex = 0;
    self.window.backgroundColor = [UIColor whiteColor];
    [self customizeAppearance];
    [self.window makeKeyAndVisible];
    return YES;
}

这样就避免了根据故事版文件的信息来加载窗口以及它所承载的界面元素。

   

时间: 2024-12-25 19:16:51

详解UIKit框架:它所定义的iOS主线程执行流程的相关文章

[转载] 多图详解Spring框架的设计理念与设计模式

转载自http://developer.51cto.com/art/201006/205212_all.htm Spring作为现在最优秀的框架之一,已被广泛的使用,51CTO也曾经针对Spring框架中的JDBC应用做过报道.本文将从另外一个视角试图剖析出Spring框架的作者设计Spring框架的骨骼架构的设计理念. AD: Spring作为现在最优秀的框架之一,已被广泛的使用,51CTO也曾经针对Spring框架中的JDBC应用做过报道.本文将从另外一个视角试图剖析出Spring框架的作者

详解Spring框架的核心思想之IOC

微信号:GitShare微信公众号:爱折腾的稻草如有问题或建议,请在公众号留言[1] 前续 为帮助广大SpringBoot用户达到"知其然,更需知其所以然"的境界,作者将通过SpringBoot系列文章全方位对SpringBoot2.0.0.RELEASE版本深入分解剖析,让您深刻的理解其内部工作原理. No.1 Spring是什么 为了让更多的朋友了解Spring,首先科普一下Spring!有兴趣的朋友可以去Spring官网逛逛,地址是:https://spring.io/ The

网络爬虫之scrapy框架详解,scrapy框架设置代理

twisted介绍 Twisted是用Python实现的基于事件驱动的网络引擎框架,scrapy正是依赖于twisted, 它是基于事件循环的异步非阻塞网络框架,可以实现爬虫的并发. twisted是什么以及和requests的区别: request是一个python实现的可以伪造浏览器发送Http请求的模块,它封装了socket发送请求 twisted是基于时间循环的异步非阻塞的网络框架,它也封装了socket发送请求,但是他可以单线程的完成并发请求. twisted的特点是: 非阻塞:不等待

详解 集合框架

我们对于数据的存储,在不同场合有不同的需求,而对于这些需求,Java给出了一个框架 -- 集合框架 集合框架: 集合的由来 : 面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,Java就提供了集合类. 数组和集合的区别 (1): 长度区别: 数组的长度是固定的 而集合的长度是可变的 (2): 存储数据类型的区别: 数组可以存储基本数据类型 , 也可以存储引用数据类型; 而集合只能存储引用数据类型 (3): 内容区别: 数组只能存储同种数据类型的元素 , 集合可以存储不同类

iOS疯狂详解之第三方微信授权登录的iOS代码分析

微信已经深入到每一个APP的缝隙,最常用的莫过分享和登录了,接下来就以代码的形式来展开微信登录的相关说明,至于原理级别的oauth2.0认证体系请参考微信开放平台的相关说明和图示 https://open.weixin.qq.com/ 微信登录授权开发 1,到微信开发平台注册相关APP,现在是等待审核成功后才能获取到对应的key和secret:获取成功后需要单独申请开通登录和支付接口,如图 2,和QQ类似,需要填写Url Schemes,如demo中的wxd930ea5d5a258f4f ,然后

详解ABP框架的多租户

(此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:ABP框架对多租户场景提供了很好的支持,内建了多租户的处理机制,今天我们来深入解析一下这一特性. 最近在基于ABP框架(ASP.NET Boilerplate)开发了一个SaaS.所以接下来可能会时不时分享一下ABP方面的文章.今天来介绍一下ABP对多租户提供的支持特性. ABP简介 ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应用程序的新起点,它旨在成为一个

深入理解Oracle表(5):三大表连接方式详解之Hash Join的定义,原理,算法,成本,模式和位图...

Hash Join只能用于相等连接,且只能在CBO优化器模式下.相对于nested loop join,hash join更适合处理大型结果集       Hash Join的执行计划第1个是hash表(build table),第2个探查表(probe table),一般不叫内外表,nested loop才有内外表       Hash表也就是所谓的内表,探查表所谓的外表       两者的执行计划形如:       nested loop           outer table    

iOS 开发之照片框架详解之二 —— PhotoKit 详解(上)

一. 概况 本文接着 iOS 开发之照片框架详解,侧重介绍在前文中简单介绍过的 PhotoKit 及其与 ALAssetLibrary 的差异,以及如何基于 PhotoKit 与 AlAssetLibrary 封装出通用的方法. 这里引用一下前文中对 PhotoKit 基本构成的介绍: PHAsset: 代表照片库中的一个资源,跟 ALAsset 类似,通过 PHAsset 可以获取和保存资源 PHFetchOptions: 获取资源时的参数,可以传 nil,即使用系统默认值 PHAssetCo

iOS PhotoKit框架 详解

一. 概况 本文侧重介绍在前文中简单介绍过的 PhotoKit 及其与 ALAssetLibrary 的差异,以及如何基于 PhotoKit 与 AlAssetLibrary 封装出通用的方法. 这里引用一下前文中对 PhotoKit 基本构成的介绍: PHAsset: 代表照片库中的一个资源,跟 ALAsset 类似,通过 PHAsset 可以获取和保存资源 PHFetchOptions: 获取资源时的参数,可以传 nil,即使用系统默认值 PHAssetCollection: PHColle