iOS开发实践:一个类微博客户端从启动到与用户交互的过程
本文基于数据字典和数据流图两种工具讲述一个完整微博客户端的实现。数据字典和数据流图都可以用来表达线程的执行流程,同时定义了需要的类,是进一步设计类的基础。
数据字典实际上是一张表,表的第一个字段是程序代码中的标识符,其它字段具体描述它在线程中被如何使用,以及它所依赖的其它元素,数据字典中各个标识符基本上也是按照线程的执行流程来排序。
数据流图是一个平面拓扑结构,每个节点或者是外部数据,或者是可被线程执行的代码模块。从外部数据到代码模块的边意味着线程在执行代码模块的时候需要用到外部数据,从代码模块到代码模块的边则表示线程执行完成一个代码模块后跳转到另一个代码模块开始执行。其它类型的边没有具体含义。
数据字典
· 线程启动,执行函数main。
· int main(int argc, char *argv[])
—— 线程首先跳转到函数main所在的代码块,然后可以跳转到函数UIApplicationMain。
· int UIApplicationMain (
int argc,
char *argv[],
NSString *principalClassName,
NSString *delegateClassName
);
—— 线程调转到函数UIApplicationMain所在的代码块,然后在内存中创建两个分别引用了应用本身和应用代理的内存块,其实就是UIApplication类(子类)和SAAppDelegate类(子类)的实例;然后调转到 app delegate 实例,执行 applicationDidFinishLaunching 方法中定义的代码;然后线程跳转到UIApplication的实例,根据实例中的字段和类中定义的代码,进入等待接收事件的状态;如果线程接收到界面控件点击事件,就跳转到引用了这个控件的内存块(控件对象),根据内存块中的字段值和控件类中定义的代码执行相应的过程,最后重新等待其它事件;如果线程接收到用户终止了进程的事件,就跳转到 app delegate 实例,执行 applicationWillTerminate 中的代码,然后再跳转到main函数,执行 return 语句终止自己。
· UIApplication
—— 类UIApplication以及它在内存中的实例中定义的代码和数据, 可以告诉线程应该如何修改和获得与应用程序相关的信息,如何进入事件循环,线程等待各种事件,跳转到相应的代码位置。
· SAAppDelegate
—— 类SAAppDelegate以及它在内存中的实例中定义的代码和数据,可以告诉线程如何处理与应用程序相关的事件,如何获取数据模型等等。
· applicationDidFinishLaunching
—— 线程从UIApplication类或实例中的代码跳转到这个函数中,然后在内存中创建一个UIWindow类的实例,这个实例可以引用一个可以承载可视化元素的窗口,然后线程在内存创建一个控制器类SAMainController或SAOAuthController或SANewfeatureController类的实例,在把UIView的实例创建到内存后,调用 viewDidLoad 方法配置 view 对象中的各个字段。然后跳转到UIWindow类的代码中,设置内存实例的字段值,并把这个ViewController的实例作为窗口的根元素,然后跳转到 makeKeyAndVisible的代码中,根据根元素实例包含的UIView实例,画出窗口中的界面元素,期间会跳转到控制器实例的 viewWilAppear 等方法,执行完成后跳转回UIApplication实例,进入等待事件的状态。
ps:makeKeyAndVisible就是一个设置主窗口的函数,表示这个窗口下的视图对象需要被渲染(rendering)。一个内存对象如果不经过渲染,也就不会对应屏幕上的元素。
数据流图(顺序图)
ps:
关于为什么要调用 performSelectorOnMainThread 才能更新界面: 因为程序员无法直接调用绘图函数,如果让程序员创建的线程来更改控件对象,那么就仅仅是改变了内存中某个实例的字段值,主线程却没有收到界面更新的事件,仍然处于阻塞状态,界面就不会更新。问题在于主线程是否会在下一次事件循环结束后更新界面。
如果我们使用模板来新建一个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),线程在内存中创建一个代理类的实例,定义一些处理与操作系统相关的事件的代码。
用代码替换故事版
说了很多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 = ;
self.window.backgroundColor = [UIColor whiteColor];
[self customizeAppearance];
[self.window makeKeyAndVisible];
return YES;
}
这样就避免了根据故事版文件的信息来加载窗口以及它所承载的界面元素。
iOS开发实践:一个类微博客户端从启动到与用户交互的过程的更多相关文章
- iOS 开发实践之 Auto Layout
原:http://xuexuefeng.com/autolayout/?utm_source=tuicool 本文是博主 iOS 开发实践系列中的一篇,主要讲述 iOS 中 Auto Layout(自 ...
- iOS开发之第三方登录微博-- 史上最全最新第三方登录微博方式实现
相关资源地址: 本项目demo地址 : https://github.com/zhonggaorong/weiboSDKDemo 最新SDK下载: 最新微博SDK 官网注册地址:点击打开链接 最新 ...
- 升讯威微信营销系统开发实践:(3)功能介绍与此项目推广过程的一些体会( 完整开源于 Github)
GitHub:https://github.com/iccb1013/Sheng.WeixinConstruction因为个人精力时间有限,不会再对现有代码进行更新维护,不过微信接口比较稳定,经测试至 ...
- iOS开发实践-OOM治理
概览 说起iOS的OOM问题大家第一想到的应该更多的是内存泄漏(Memory Leak),因为无论是从早期的MRC还是2011年Apple推出的ARC内存泄漏问题一直是iOS开发者比较重视的问题,比如 ...
- iOS 开发学习-类的创建与实现,与java语言的对比
Person.h #import <Foundation/Foundation.h> @interface Person : NSObject { //在{}中定义属性(全局变量/实例变量 ...
- iOS开发实践之多线程(单例模式)
单例模式的作用:可以保证在程序运行过程,一个类只有一个实例,而且该实例易于供外界访问,从而方便地控制了实例个数,并节约系统资源. 单例模式的使用场合:在这个应用程序中,共享一份资源(这份资源只需要创建 ...
- iOS开发:一个高仿美团的团购ipad客户端的设计和实现(功能:根据拼音进行检索并展示数据,离线缓存团购数据,浏览记录与收藏记录的批量删除等)
大致花了一个月时间,利用各种空闲时间,将这个客户端实现了,在这里主要是想记录下,设计的大体思路以及实现过程中遇到的坑...... 这个项目的github地址:https://github.com/wz ...
- iOS开发笔记14:微博/微信登录与分享、微信/支付宝支付
产品中接入了微博/微信的第三方登录分享功能.微信和支付宝的第三方支付功能,之前在开发过程中涉及到这些部分,于是抽空将接入过程梳理了一遍. 1.微博.微信.支付宝SDK相关接入设置 (1)微博SDK S ...
- iOS 开发自定义一个提示框
在开发的时候,会碰到很多需要提示的地方,提示的方法也有很多种,ios 8 以前的版本有alertview还是以后用的alertController,都是这种作用, 但是不够灵活,而且用的多了,用户体验 ...
随机推荐
- ssh连接慢
suse刚装完,开始用ssh的时候,总会遇到这样的问题:输入了用户名以后,等半天才出输入密码的框,很是急人.这是dns反查造成的.解决方法:编辑 /etc/ssh/sshd_conf , 将 #Use ...
- HTML/CSS中常遇到的bug 一些注意事项总结
1.IE6下横向双倍margin bug (触发条件:块属性标签:float:横向margin设置:IE6下.解决办法:css中加入display:inline.) 2.css中公用属性首先声明:如对 ...
- 集合上的动态规划---最优配对问题(推荐:*****) // uva 10911
/* 提醒推荐:五星 刘汝佳<算法竞赛入门经典>,集合上的动态规划---最优配对问题 题意:空间里有n个点P0,P1,...,Pn-1,你的任务是把它们配成n/2对(n是偶数),使得每个点 ...
- js刷新
jquery刷新页面的实现代码(局部及全页面刷新) 发布:mdxy-dxy 字体:[增加 减小] 类型:转载 jquery刷新页面的实现代码(局部及全页面刷新) ,需要的朋友可以参考下. 局部刷新: ...
- 2016,除了 DevOps,企业还应该知道 CMDB!
CMDB 是 Configuration Management Database(配置管理数据库)的简称,CMDB 存储与管理企业 IT 架构中设备的各种配置信息,它与所有服务支持和服务交付流程都紧密 ...
- 如何深入理解 StatsD 与 Graphite ?
众所周知,StatsD 负责收集并聚合测量值.之后,它会将数据传给 Graphite,后者以时间序列为依据存储数据,并绘制图表.但是,我们不知道,基于 http 访问的图表在展示时,是基于每秒钟的请求 ...
- C# 委托的”四步走“
看了一本<深入了解C#>感觉很不错,对于委托的讲解,给大家摘录了下来! 1.什么是委托 我的拙见:委托就是将方法作为参数,进行传递的 书中的记载:将某种行为“包含”在一个对象中,这个对象可 ...
- ElasticSearch小操之Marvel,Sense
慢慢弄弄,说不好马上就要用呢,,, 嘿嘿 参考网址: http://es.xiaoleilu.com/ Elasticsearch 权威指南(中文版) 阅读地址:Elasticsearch权威指南(中 ...
- 深入理解JVM--类的执行机制
在完成将class文件信息加载到JVM并产生class对象之后,就可以执行Class对象的静态方法或者实例方法对对象进行调用了.JVM在源代码编译阶段将源代码编译为字节码文件,字节码是一种中间代码的方 ...
- linux入门教程(二) 图形界面还是命令窗口
对于linux的应用,我想大多数都是用在服务器领域,对于服务器来讲真的没有必要跑一个图形界面.所以我们平时安装linux操作系统时往往是不安装图形界面的.说到这里也许你会有疑问,图形界面还能选择装或者 ...