[New Learn]被嫌弃的app的一生
1.简介
为什么叫被嫌弃的app的一生?致敬电影《被嫌弃的松子的一生》。
自学IOS东一锄西一镐的总感觉没有一个总的概念,还是多看看官网吧,先看一下一个app的整个生命周期,本文主要是翻译官方文档:https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/TheAppLifeCycle/TheAppLifeCycle.html#//apple_ref/doc/uid/TP40007072-CH2-SW1
APP生命周期
Apps其实是客户代码和系统框架进行复杂整合的产物。特定的系统框架为所有运行在其中的apps提供最最基本的基础功能,具体的apps的功能表现需要开发者自己去通过代码来实现的。为了后续开发的效率,这篇文章帮助你了解一点IOS框架的基本原理和工作机制。
iOS框架同通过 model-view-controller和代理的设计模式来实现的。了解其设计模式对于开发一个app是大有益处的。这也帮助你更好地去熟悉和适应Objective-c语言和它的特性。如果你是一个iOs开发新手,最好的方式是从阅读《Developing iOS Apps Today》开始。
Main函数
任何基于C的语言所编写的程序都是以main函数为入口的,iOS应用也不例外。唯一的区别是在编写iOs应用的时候你不需要自己去实现main函数,Xcode工具会在你创建工程的时候就自动为你创建好了。Listing 2-1展示了main函数的例子。一般的你不需要去修改Xcode为你提供的默认实现。
Listing 2-1 The main
function of an iOS app
#import <UIKit/UIKit.h> #import "AppDelegate.h" int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } }
唯一需要注意的是main函数的任务就是去和UIKit框架进行连接。UIApplicationMain函数创建应用的和兴对象,从storyboard文件中加载用户界面信息,调用客户代码去初始化并且启动应用的runloop功能。在整个过程中用户代码初始化代码和storyborad文件是需要开发人员准备好的。
一个APP的结构
在启动期间,UIApplicationMain函数启动了若干个关键对象并以此启动了应用。对于任何一个应用来说UIApplucation对象是核中的核心,这个对象的任务就是在系统和应用中的对象之间建立起一个通信机制。 Figure 2-1展示了一个应用中的关键对象,而Table 2-1 列表则描述了每一个对象的作用。首先需要注意的是iOs应用使用的是model-view-controller架构。这种模式将应用的数据和业务逻辑通过数据持久层来分开。这种架构是一个应用能够运行在不同屏幕尺寸的设备上的关键因素。
Figure 2-1 Key objects in an iOS app
对象 |
描述 |
---|---|
UIApplication对象管理着事件loop和其他高级别的应用行为。同时也负责生成应用的状态建议和一些特殊的事件(如push通知等)给用户定义的代理。UIApplication在使用的时候不用去子类化他,直接使用即可。 |
|
应用的代理是用户代码的核心。这个对象和UIApplication对象是串联的,负责去进行应用的初始化,状态迁移和很多高级别的应用实践。每一个应用中这个对象是必定存在的,所以经常被用于进行应用的数据初始化工作。 |
|
Documents and data model 对象 |
Data model对象存储应用的具体内容,不同应用有其不同的对象特性。例如,在一个银行类的app中你需要一个带有财务事务的数据库对象,而在一款绘画app中可能需要存在一个图片对象或者一个用于保存绘画指令的对象来建立你的图像。(说白了最后图像对象最终也是一个数据对象因为他只包含了某图片的具体信息) 应用也可以使用document对象(可以继承UIDocument)去管理一些或者全部的data model对象。Document对象并不是必须的但是他且提供了另外一种方便的方式去管理数据。了解更多信息可以参考Document-Based App Programming Guide for iOS. |
View controller 对象 |
试图控制器对象管理者你屏幕上所要显示的内容。一个视图控制器管理一个视图和这个试图的一组子视图。当需要显示视图的时候,视图控制器会将这些要显示的试图安装进应用的window。
关于如何使用视图控制器可以参考View Controller Programming Guide for iOS. |
|
UIWindow对象负责协调一个或者多个视图在屏幕上的显示。大多数应用只有一个window,主要工作就是在主屏幕上呈现内容,但是应用可以额外有一个window去管理外部显示。 在你的应用运行中,显示的内容改变的时候,内部是使用了一个视图控制器去改变了相应的window中的视图,对于Window来说并不会改变或者重建。 除了加载视图外,Window还和UIApplication对象一起向视图或者视图控制器传递事件。 |
View objects, control objects, and layer objects |
视图和控件提供了可视化的应用信息内容。一个视图是一个将内容华仔在一个指定大小的矩形区域中并只在这个矩形区域去相应事件的一个对象。Controls是一个特殊的视图,主要是系统为了提供一些友好的内置的控件诸如按钮,文本框和开关等。 UIKit框架提供了标准的视图去呈现不同类型的页面内容。你也可以通过直接集成 除了有视图和controls外,应用也在视图和控件层级提供了核心的动画层。层对象实际上是一种数据对象他描绘了一种视觉效果。视图使用层对象来进行场景的变化。你也可以增加自己的层对象来完成复杂的酷炫的视觉效果。 |
一个应用和另外一个应用的区别就在与他所管理的数据(和在数据之上的逻辑)和将数据呈现给用户的方式上。大多数和UIKit框架对象交互的行为并不能够定义你的应用而是帮助你来规范行为。例如,应用的代理会通知你应用的某个状态发生了改变这样你就可以写代码逻辑来处理作出回应。
Main Run Loop
一个应用的main run loop处理所有用户相关的时间。UIApplication对象在启动的时候创建了main run loop并且使用它来处理事件和基于视图的接口状态更新。就如其名,main run loop在主线程中运行。这样就保证了用户事件会被先到先处理的有序顺序被处理。
Figure 2-2展现了main run loop的架构和用户事件处理的过程。当用户操作设备的时候,系统将生成相对应的事件并通过UIKit框架设定的专用端口将事件转发给应用。在应用内部事件将被排列一个一个的转发给main run loop去执行。UIApplication对象是第一个接受到事件的对象,他会做出判断此事件应该如何处理。对于触摸事件来说通常转发给主Window对象,后者再将此对象发送给触摸事件发生的视图。其他事件会转发给应用对象,只是转发路径上面会有稍稍不同。
翻者http://home.cnblogs.com/u/ios123/注:下面这个图还是有点不够清晰,事件队列是应该属于应用的,下图没有表达清楚。
Figure 2-2 Processing events in the main run loop
iOs应用能够接受和转发多种类型的事件。最常见的事件类型见Table 2-2表。大多数事件类型使用main run loop进行转发,但是有一些却不是。很多事件是发送给代理对象或者直接传送给block的。对于系统是如何处理大多数事件类型--包括触摸、远程、运动、加速剂和陀螺仪事件可以参考Event Handling Guide for iOS.
事件类型 |
转发给… |
备注 |
---|---|---|
Touch 触摸事件 |
事件发生地的视图 |
Views are responder objects. Any touch events not handled by the view are forwarded down the responder chain for processing. 视图是一个responder对象。任何触摸事件如果没有被目标事件处理则会进入响应者链进行寻找处理者去处理 |
Remote control 远程事件 Shake motion events 晃动事件 |
第一响应者 |
Remote control events are for controlling media playback and are generated by headphones and other accessories. 远程控制事件是由耳机或者遥控器等附加设备触发来控制流媒体的设计所触发的。 |
Accelerometer加速计 Magnetometer磁力计 Gyroscope陀螺仪 |
The object you designate 指定对象 |
Events related to the accelerometer, magnetometer, and gyroscope hardware are delivered to the object you designate. 加速计,陀螺仪和磁力计相关的硬件事件被转发给预先指定的对象进行处理。 |
Location 位置 |
The object you designate 指定对象 |
You register to receive location events using the Core Location framework. For more information about using Core Location, see Location and Maps Programming Guide. 你可以使用Core Location framework去注册和接受一个位置事件。关于Core Location框架的内容详细可参考Location and Maps Programming Guide. |
Redraw 重绘 |
The view that needs the update 视图更新 |
Redraw events do not involve an event object but are simply calls to the view to draw itself. The drawing architecture for iOS is described in Drawing and Printing Guide for iOS. 重绘事件并不是一个事件对象但是他只是简单的去通知视图重绘自身。关于绘制机制的描述可以参考Drawing and Printing Guide for iOS. |
很多事件,诸如触摸事件和远程控制事件将会被应用的响应者对象处理。响应者对象可能在你应用的任何地方存在(UIApplication对象,视图对象和 视图控制器对象都可能是响应者
)大多数事件会指定一个响应者对象但是如果事件有特殊要求也可以通过响应者链机制去传递给不同的对象。例如,视图不处理事件的话可以将事件传递给他的superview或者一个视图控制器。
controls控件(比如按钮)引起的触摸事件的处理方式和其他类型的视图引起的触摸事件的处理方式不太一样。他们通常会包装一个target-action对,目标是可以指定的这样开发人员就可以方便的去使用空间去控制处理逻辑。
应用的执行状态
在任何时候,你的应用都会处于Table 2-3表中所列的某个状态下。系统将使你的应用从一种状态迁移到另外一个状态,当用户按下home按钮的时候,当电话接入的时候,或者任何其他的打断事件发生的时候,当前运行的应用都会发生状态变化,在Figure 2-3展示了应用的状态之间的迁移路径。
状 态 |
描述 |
---|---|
Not running |
The app has not been launched or was running but was terminated by the system. 应用没有被加载或者曾经运行过但是被系统关闭了。 |
Inactive |
The app is running in the foreground but is currently not receiving events. (It may be executing other code though.) An app usually stays in this state only briefly as it transitions to a different state. 应用正在前台运行但是当前不会接受任何时间。一个应用通常在做状态转化的时候会极其短暂的处于这种状态。 |
Active |
The app is running in the foreground and is receiving events. This is the normal mode for foreground apps. 一个应用正在前台运行并且能够接受时间。这种是正常的前台应用的状态。 |
Background |
The app is in the background and executing code. Most apps enter this state briefly on their way to being suspended. However, an app that requests extra execution time may remain in this state for a period of time. In addition, an app being launched directly into the background enters this state instead of the inactive state. For information about how to execute code while in the background, see Background Execution. 应用正在后台运行。大多数应用会在过渡为suspended状体的时候短暂的处于这个状态。然而,当一个应用需要额外的执行时间的时候会在这个状态下保持一段时间(既后台可以运行的程序,比如导航神马的)。另外,一个应用会直接的进入background状态而不会经历inactive状态。关于如何在background状态下执行代码可以参考Background Execution. |
Suspended |
The app is in the background but is not executing code. The system moves apps to this state automatically and does not notify them before doing so. While suspended, an app remains in memory but does not execute any code. When a low-memory condition occurs, the system may purge suspended apps without notice to make more space for the foreground app. 应用在background状态而且没有什么额外的逻辑代码需要运行的时候系统自动地将应用转入这个状态。当处于suspended状态的时候,应用依然保持着他的内存空间但是并不会执行任何代码,当低内存报警发生的时候,系统可能会为了使前台应用能够流畅运行会清理掉这些个suspended应用 |
Figure 2-3 State changes in an iOS app
大多胡状态迁移会伴随着调用代理对象的方法。这些方法使得你有机会去为状态变化而去做一些额外的处理动作。这些方法如下,
application:willFinishLaunchingWithOptions:
—当应用加载的时候首先会调用此方法application:didFinishLaunchingWithOptions:
—在应用呈现在屏幕上之前你可以做一些初始化动作的最后机会。applicationDidBecomeActive:
— 当你的应用状态转化为前台运行的时候触发。applicationWillResignActive:
—当应用从前台运行状态发生状态迁移的时候触发。applicationDidEnterBackground:
—当你的应用处于background状态并且随时会切入suspended状体之前。applicationWillEnterForeground:
— 当应用从后台转换为前台的时候但是此时还未处于active状态的时候。applicationWillTerminate:
—当应用被关闭的时候。这个在应用处于suspended状态的时候并不会被调用。
应用终止
应用必须必须做好被随时终止的准备并且不应该在被终止之前去保存数据或者其他重要的任务。系统终止一个应用是一件极其正常的事情。系统通常会为了腾出内存空间去运行其他应用而杀死后台应用,但是系统可能也会在毫无征兆的情况就将应用杀死,所以开发人员要有应用随时被杀死的可能的觉悟。
Suspended状态下的应用不会收到应用内终止的通知;系统将杀死进场释放内存。如果一个应用正在后台运行处于background不是处于suspended状态,系统将会调用applicationWillTerminate:代理方法来通知应用你要被干掉了。当然当设备被重启的时候可不要指望谁来通知你的应用。
另外关于系统终止应用场景,用户可能终止程序,基于用户的这个终止行为可基于系统杀死suspended状态下的应用行为一样,应用不会获得任何通知。
线程和并发
系统会创建一个应用的主线程并且如有需要开发人员可以创建额外的其他线程来运行其他任务。对于iOS应用来说,开发人员偏爱的多线程计数是GCD,operation对象和其他异步技术,绝对不要自己去创建和管理线程,那将是非常易错和痛苦的。GCD技术让开发人员自定义任务的执行方式和执行顺序,但是在底层层面上系统将最终决定最好的的执行过程。让系统来处理任务的执行使得开发人员更加专注业务和性能。
当你考虑线程和并发的时候,想想以下这些注意点:
- 当任务是为了视图,Core Animation和其他UIkit相关的类而运行的那么通常需要在主线程中执行。也有一些例外情况--比如,基于图片的处理就进场在后台线程中运行--但是当出现任何疑问的时候务必请考量一下这个规则你是否遵守了。
- 长任务应该被运行在后台线程中,任何和网络,文件读取和大数据处理都应该使用GCD或者operation对象来进行并发运行而不要阻塞主线程,不然你的应用出现卡顿现象。
- 在应用加载的时候,尽量的将任务不要运行在主线程中。在加载的时候,你的应用应该尽快的加载用户接口尽快的呈现给用户。
详细的关于GCD和operation对象的技术科参考Concurrency Programming Guide.
[New Learn]被嫌弃的app的一生的更多相关文章
- [Learn AF3]第二章 App Framework 3.0的组件View——AF3的驱动引擎
View:af3中的驱动引擎 组件名称:View 使用说明:按照官方的说法,view组件是af3的“驱动引擎(driving force)”,view是af3应用的基础,一个app中可以包 ...
- 《Python》re模块补充、异常处理
一.re模块 1.match方法 import re # match 验证用户输入的内容 ret = re.match('\d+', 'hhoi2342ho12ioh11') print(ret) # ...
- 学习Maven之Cobertura Maven Plugin
cobertura-maven-plugin是个什么鬼? cobertura-maven-plugin是一个校验单元测试用例覆盖率的工具,可以生成一个测试覆盖率报告,可以给单元测试用例编写提供参考. ...
- 学习Maven之Maven Surefire Plugin(JUnit篇)
1.maven-surefire-plugin是个什么鬼? 如果你执行过mvn test或者执行其他maven命令时跑了测试用例,你就已经用过maven-surefire-plugin了.maven- ...
- 小试牛刀--利用豆瓣API爬取豆瓣电影top250
最近得赶进度爬点东西,对于豆瓣,它为开发者提供了API,目前是v2版本,目前key不对个人开放,但是可以正常通过其提供的API获取数据.豆瓣V2版API权限分3类:公开.高级.商务,我们用开放基本数据 ...
- iOS 10.0 更新点(开发者视角)
html, body {overflow-x: initial !important;}html { font-size: 14px; } body { margin: 0px; padding: 0 ...
- What's New in iOS9 iOS9功能改进
What's New in iOS9 This article summarizes the key developer-related features introduced in iOS 9, w ...
- java 笔记(3) —— 动态代理,静态代理,cglib代理
0.代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口. 代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等. 代理类与委托类之间通常会存 ...
- Differences Between Xcode Project Templates for iOS Apps
Differences Between Xcode Project Templates for iOS Apps When you create a new iOS app project in Xc ...
随机推荐
- 【BZOJ5297】【CQOI2018】社交网络(矩阵树定理)
[BZOJ5297][CQOI2018]社交网络(矩阵树定理) 题面 BZOJ 洛谷 Description 当今社会,在社交网络上看朋友的消息已经成为许多人生活的一部分.通常,一个用户在社交网络上发 ...
- BZOJ1499:[NOI2005]瑰丽华尔兹——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=1499 舞厅是一个N行M列的矩阵,矩阵中的某些方格上堆放了一些家具,其他的则是空地.钢琴可以在空地上滑 ...
- excel 列索引(数字)转列名
function index2ColName($columnNumber) { $dividend = $columnNumber; while ($dividend > 0) { $modul ...
- 【转】TCP拥塞控制,慢启动、拥塞避免、快重传以及快恢复
转自:http://blog.csdn.net/yusiguyuan/article/details/22847787 注:本文绝大部分是来自转载的博客,还补充了少量内容. 一.TCP的拥塞控制 拥塞 ...
- PLAN OF HEOI(unfinished)
Au:整体二分/计算几何/多项式/fwtAg:可持久化重量平衡树/线段树分治/线段树合并/最短路树/最短路DAGCu:三分Up:博弈论/置换群/杜教筛/矩阵树定理/BSGS/动态树分治/网络流(线性规 ...
- 使用snmp4j实现Snmp功能(三)
相关链接:Snmp学习笔记使用snmp4j实现Snmp功能(一)使用snmp4j实现Snmp功能(二)使用snmp4j实现Snmp功能(三) 前两篇文章讲了如何使用Snmp4j实现Set.Get(使用 ...
- linux 命令后台运行(转载)
原文连接:https://www.cnblogs.com/lwm-1988/archive/2011/08/20/2147299.html 有两种方式: 1. command & : 后台运行 ...
- String作为输出型参数时获取不到值
有时候在一个方法中,我们需要返回多个字符串,而又不想将这些字段包成一个类.此时就需要使用输出型参数. 但是如果将输出型参数的类型声明为String,那么调用该方法后,是获取不到我们想要的值的. 测试代 ...
- Linux系统查看系统信息
1. CPU # lscpu # cat /proc/cpuinfo //可以知道每个cpu信息,如每个CPU的型号,主频等 2. 内存 # free -m # cat /proc/meminfo / ...
- Linux 使用代理使网速变快
$ export http_proxy="http://USER:PASSWORD@PROXY_SERVER:PORT" $ export https_proxy="ht ...