iOS基础 - iOS程序启动原理

1、UIApplicationMain

main.mmain函数中执行了UIApplicationMain这个方法,这是ios程序的入口点ios

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

argcargvISO C标准main函数的参数,直接传递给UIApplicationMain进行相关处理便可windows

principalClassName:指定应用程序类,该类必须是UIApplication(或子类)。若是为nil,则用UIApplication类做为默认值app

delegateClassName:指定应用程序类的代理类,该类必须遵照UIApplicationDelegate协议框架

此函数会根据principalClassName建立UIApplication对象,根据delegateClassName建立一个delegate对象,并将该delegate对象赋值给UIApplication对象中的delegate属性编辑器

UIApplication对象会依次给delegate对象发送不一样的消息,接着会创建应用程序的main runloop(事件循环),进行事件的处理(首先会调用delegate对象的 application:didFinishLaunchingWithOptions:)ide

程序正常退出时这个函数才返回。若是进程要被系统强制杀死,通常这个函数还没来得及返回进程就终止了函数

 

2、UIApplication

UIApplication是应用程序的核心,每个程序在运行期必须有UIApplication(或子类)的一个实例(有且仅有一个),经过[UIApplication sharedApplication]能够获得这个单例实例的指针oop

UIApplication帮助管理应用程序的生命周期,而它经过delegate来履行这个任务动画

UIApplication能够接收事件,把全部用户事件都放入队列,逐个处理,它会发送当前事件给一个合适的目标控件进行处理。它还将部分事件转给delegate对象来处理,delegate可处理的事件包括:应用程序的生命周期事件(如程序启动和关闭)、系统事件(如来电)

[UIApplication sharedApplication].windows: 在本应用中打开的UIWindow列表,这样就能够接触应用中的任何一个UIView对象

[UIApplication sharedApplication].keyWindow: 用来接收键盘以及非触摸类的消息事件的UIWindow,并且程序中每一个时刻只能有一个UIWindowkeyWindow。若是某个UIWindow内部的文本框不能输入文字,多是由于这个UIWindow不是keyWindow

 

3、UIApplicationDelegate

在开发过程当中,UIApplication是一个很是重要的全局对象。但在实际编程中咱们并不直接和UIApplication对象打交道,而是和其代理打交道,它的代理必须遵照UIApplicationDelegate协议,代理提供了相关的生命周期方法来处理应用程序的系统事件

ios设备的内存极其优先,若是为app分配了太多内存,操做系统会终止app的运行,在UIApplication接收到这个事件后它会调用代理的applicationDidReceiveMemoryWarning方法,代理在这个方法内能够进行释放内存的操做以防止操做系统强制终止应用程序的运行

ios并非多任务的操做系统,因此app很容易受到打扰。好比一个来电可能致使app失去焦点,若是这个时候接听了电话,那么app会自动终止运行

还有不少其它相似的事件会致使app失去焦点

app失去焦点前会调用代理的applicationWillResignActive

app再次获取焦点时会调用代理的applicationDidBecomeActive

在运行app时锁屏会调用代理的applicationWillResignActive

当屏幕被解锁时,会调用代理的applicationDidBecomeActive

 

4、UIWindow

UIWindow是一种特殊的UIView,一般在一个app中只会有一个UIWindow,但能够手动建立多个UIWindow

UIWindow的主要做用:

提供一个区域来显示视图

将事件分发给视图

UIViewController协同工做,方便完成设备方向旋转的支持

添加UIViewUIWindow中两种常见方式:

addSubview:直接将UIView添加到UIWindow中,程序负责维护UIView的生命周期以及刷新,但并不会理会UIView对应的UIViewController

rootViewController:自动将UIViewController对应的UIView添加到UIWindow中,同时负责维护UIViewControllerUIView的生命周期

经常使用方法

makeKeyWindow:让当前UIWindow变成keyWindow

makeKeyAndVisible:让当前UIWindow变成keyWindow,并显示出来

 

5、UIViewController

UIViewController属于MVC模型中的C(Controller),说的更具体点它是一个视图控制器,管理着一个视图(UIView)

一个UIViewController应该只管理一个view hierarchy,一般来讲一个完整的view hierarchy指的是占满整一个屏幕。而不少app满屏中会有各个区域分管不一样的功能,一些开发者喜欢直接新建一个UIViewController和一套相应的view来完成所要的功能,这样作彻底不符合Apple提供的设计规范

 

6、UIViewControllerview

能够利用xib文件来初始化view; 也可使用自定义的view,那就必须覆盖loadView方法来建立这个view

UIViewControllerviewlazy loading,当你访问其view属性时,view会从xib文件载入或者经过代码建立(覆盖loadView方法,自定义其view hierarchy) 

能够用isViewLoaded方法判断一个UIViewControllerview是否已经被加载

 

7、UIViewController生命周期方法的调用

view加载后调用viewDidLoad,这里能够进行一些数据的请求或加载,用来更新界面

view将要被加入view hierarchy时调用viewWillAppear,完成加入时调用viewDidAppear

view将要从view hierarchy中移除时调用viewWillDisappear,完成移除时调用viewDidDisappear

当内存紧张时调用didReceiveMemoryWarning,其默认实现是若是当前UIViewControllerviewsuperviewnil,则将view释放且调用viewDidUnload, viewDidUnload中你能够进行后继的内存清理工做(主要是界面元素的释放,当再次加载的时候须要重建)

(这里的view是指UIViewController内部的view属性)

 

8、工程名-Info.plist

创建一个工程后,会在Supporting files文件夹下看到一个”工程名-Info.plist”的文件,该文件对工程作一些运行期的配置,很重要,不能删除

在旧版本Xcode建立的工程中,这个配置文件的名字就叫”Info.plist

若是使用文本编辑器打开这个文件,会发现这是一个XML格式的文本文件,通常不用文本编辑器直接编辑这个文件,而是经过Xcode编辑

项目中还有一个InfoPlist.strings的文件,跟Info.plist文件的本地化相关

常见属性(红色部分是用文本编辑器打开时看到的key)

Localiztion native development region(CFBundleDevelopmentRegion)-本地化相关

Bundle display name(CFBundleDisplayName)-程序安装后显示的名称,限制在1012个字符,若是超出,将被显示缩写名称

Icon file(CFBundleIconFile)-app图标名称,通常为Icon.png

Bundle version(CFBundleVersion)-应用程序的版本号,每次往App Store上发布一个新版本时,须要增长这个版本号

Main nib file base name(NSMainNibFile)-nib文件的名称

Bundle identifier(CFBundleIdentifier)-项目的惟一标识,部署到真机时用到

 

9、工程名-Prefix.pch

通常来讲,能够将项目中常常用到的一些头文件放在这里来import,整个项目均可以访问这个文件的内容,这样既节省了手动添加import的时间,也有助于加速编译

在这里定义的宏,整个项目均可以访问

pch文件中添加下列预处理指令,而后在项目中使用Log()来输出日志信息,就能够在发布应用的时候,一次性将NSLog语句移除(在调试模式下,才有定义DEBUG

#ifdef DEBUG

#define Log(...) NSLog(__VA_ARGS__)

#else

#define Log(...) /* */

#endif

 

10、开发iOS6的注意

iOS6新特性:auto layout属性,此属性只针对iOS6及以上版本 

iOS6如下版本运行时可能会出现的异常信息:

Terminating app due to uncaught exception NSInvalidUnarchiveOperationException, reason: Could not instantiate class named NSLayoutConstraint 

具体场景:Xcode 4.5 选择iPhone/iPad 5.0/5.1 Simulator(模拟器) 

解决办法:须要关闭storyboardxib界面文件的Use Autolayout 选项,这是由于Auto Layout特性是iOS 6新增长的,在以前的 5.0/5.1 Simulator模拟器中不支持

 

11、nib文件

nib文件是iOS中用来描述视图的xml格式的文本文件,如今拓展名为xib,用Interface Builder打开能够生成图形界面式的描述

某书中著名的一句话:Interface Builder把窗口、菜单栏以及窗口上的各类控件对象都”冻结”在一个NIB文件里;程序运行时,这些对象将会”苏醒”

加载Nib文件时,会将文件中的描述转化为应用程序能够操做的真正对象,全部在Interface Builder中创建的关联(如Files Owner和其余对象之间的关联)都可以在运行时从新创建起来

 

12、主nib文件

nib文件是指应用程序一启动就装载的nib文件,它的Files Owner必定要是个UIApplication(或子类),而且新建一个delegate对象、创建UIApplicationdelegate对象的关联

 

十3、UIView

UIViewiOS中界面元素的基础,全部的界面元素都继承它,能够说在iPhone中你能看到的、摸到的,都是UIView

UIView的基本功能:

绘图和动画(CALayerCAAnimation实现)

事件处理(继承了UIRsponder)

一个UIView能够包含和管理若干个子视图,决定着子视图的位置和大小

 

十4、UIView经常使用方法和属性

frame 

在父视图坐标系中的位置(CGPoint origin)和大小(CGSize size)

bounds

在本视图坐标系中的位置(CGPoint originxy永远为0)和大小(CGSize size)

center

视图的中点在父视图坐标系中的位置

UIView *superview 父视图

NSArray *subviews 全部的子视图

UIWindow *window  当前视图所在的窗口

BOOL userInteractionEnabled YES表明接收触摸事件

- (void)removeFromSuperview

从父视图中移除(当前视图的计数器会-1)

- (void)addSubview:(UIView *)view

添加一个子视图(新添加的子视图在父视图的最上面,子视图的计数器会+1)

- (UIView *)viewWithTag:(NSInteger)tag

根据tag找到对应的子视图

 

十5、UIKit坐标系

View1View2的父视图

View2.frame = {x=70,y=50,width=60,height=40}

View2.bounds = {x=0,y=0,width=60,height=40}

View2.center = (x=100, y=70)

UIKit框架中的坐标系都如左图所示,视图的左上角为原点(0,0)x轴向右正向延伸,y轴向下正向延伸

View3framexy:

若是绿色视图是View3的父视图,那么View3xy为红色箭头的长度

若是View1View3的父视图,那么View3xy为蓝色箭头的宽度

 

十6、iOS关闭键盘

方法1

调用UIViewendEditing方法,例如

[self.view endEditing:YES];

成功关闭键盘的条件:self.view或者其子视图是第一响应者

方法2

递归找到第一响应者,让它把键盘给退回去

[[self findFirstResponder:self.view] resignFirstResponder];

- (UIView*)findFirstResponder:(UIView*)view {

    for ( UIView *childView in view.subviews ) {  // 遍历子视图

    if ( [childView respondsToSelector:@selector(isFirstResponder)] 

&& [childView isFirstResponder] ) {  

            return childView; // 若是childView是第一响应者

 }

        UIView *result = [self findFirstResponder:childView];

        if (result)  return result;

    }

    return nil;

}

相关文章
相关标签/搜索