第1章 iOS基础
1.1 iOS发展历史
1.iPhone OS 1.0
2007 iPhone Runs OS X、3.5大屏幕、多点触控、简洁UI、颠覆传统
2.iPhone OS 2.0
2008 iPhone OS、App Store、收入三七分成
3.iPhone OS 3.0
2010 iOS3.2、划时代、针对iPad优化
4.iOS 4
2010改名iOS、26%市场、乔布斯设计团队复杂的光影效果、仿真拟物风格
5.iOS 5
新增Siri、通知中心
6.iOS 6
2012年6月
7.iOS 7
2013 设计风格转为扁平化设计
8.iOS 8
2014
9.iOS 9
10.iOS 10
1.2 iOS特性
1.界面设计
多点触控、交互方式
2.iOS内置大量应用程序
3.第三方支持
App Store
4.硬件支持
多点触摸和手势、统一的屏幕尺寸、高分辨率、重力加速器、指南针、蓝牙和Wi-Fi连接
1.3 iOS架构
- iOS可以看作底层和高层的集合
Cocoa Touch
Media
Core Services
Core OS
- 高层框架:为底层框架提供面向对象的抽象,可以减少编写的代码行数,对复杂功能的封装,让编写代码更加容易。并没有屏蔽底层技术,开发者也可以直接使用底层框架
1.3.1 Cocoa Touch层
包含创建iOS应用所需的关键框架,开发时尽量不要使用更底层的框架,尽可能使用该层的框架
1.Cocoa Touch层高级特性
- 多任务
- 数据保护
- 推送通知服务
- 本地通知
- 点对点服务
- 标准系统视图控制器
2.Cocoa Touch层包含的框架
- Address Book UI 框架:联系人页面
- Event Kit UI 框架:用户日程、日历
- Game Kit 框架
- iAd 框架:iOS 10已废弃
- Map Kit框架
- Message UI框架
- UIKit框架
1.3.2 媒体层
- iOS高层框架:快速创建
- iOS底层框架:完成特定需求的创建
1.媒体层高级属性
- 图形、视频、音频
2.媒体层包含的框架(常用)
- AVFoundation 框架
- Core Audio 框架
- Core Graphics 框架
- Core Text 框架
- Core Video 框架
- Image I/O 框架
- 媒体播放器框架
- OpenGL ES 框架
- OpenAL 框架
- Quartz Core 框架
- 资产库框架
1.3.3 Core Services 层
提供基础服务,是系统很多部分赖以构建的基础
1.Core Services层高级特性
- 快对象
- Grand Gentral Dispatch---GCD
- 应用内购买
- 定位服务
- SQLite库
- XML支持:NSXMLParser类解析元素
2.Core Services层包含的框架
- AddressBook 框架
- CFNetwork框架
- Core Data框架
- Core Foundation框架
- Core Location框架
- Core Media框架
- Core Telephony框架
- Event Kit框架
- Foundation框架
- Mobile Core Services框架
- Quick Look框架
- Store Kit框架
- System Configuration框架
1.3.4 Core OS层
直接处理安全事务或和某个外设通信时,必须用到该框架。
- Accelerate框架
- External Accessory框架
- Security框架
- System框架
1.4 Objective-C概述
- Smalltalk特性
1.5 比较iOS和macOS
1.5.1 UIKit与AppKit的对比
1.5.2 Foundation框架的差异
1.5.3 其他框架的改变
1.6 iOS开发环境和工具
1.6.1 了解Xcode
1.6.2 Xcode导航面板
- 项目导航
- 符号导航:以类、方法、属性的形式来显示项目中所有的类、方法和属性,方便快速定位
- 搜索导航
- 问题导航
- 测试导航:白盒测试结果
- 调试导航
- 断点导航
- 日志导航
1.6.3 Xcode检查器面板
左边
- 文件路径
- 自动换行等
右边 - 详细帮助信息
- 参考手册
- 使用指南等
xib等多出的功能 - 身份检查器
- 属性检查器
- 大小检查器
- 连接检查器
1.6.4 Xcode库面板
- 文件模版库
- 代码片段库
- 对象库
- 媒体库
1.6.5 使用帮助
1.使用快速帮助面板
2.利用搜索框
3.利用编辑区的快速帮助
1.7 使用Xcode
1.7.1 案例:编写第一个Objective-C程序
main函数的作用:
- 创建自动释放池
文件后缀的含义:
- .cpp : C++语言源文件
- .mm : C++语言源文件(实现.h文件)
- .o : 编译后的文件
- .app : 编译后的可执行文件(可在iPhone、iPad或macOS上运行的文件)
1.7.2 案例:创建第一个项目
1.8 小结
第2章 数据类型和运算符
2.1 数据类型分类
- OC是强类型语言
- 指针类型是OC最重要的类型,所有的系统类、自定义类的本质都是指针类型
2.2 简单数据类型
2.2.1 整型
2.2.2 案例:输出格式字符
2.2.3 浮点型
2.2.4 字符型
2.2.5 案例:定义字符串
- NSString不是简单数据类型,而是一个对象类型
2.2.6 枚举型
2.2.7 布尔型
2.3 类型转换
2.3.1 案例:自动类型转换
- 溢出:把取值范围大的变量的值付给取值范围小的变量时
2.3.2 案例:强制类型转换
- (类型说明符)(表达式)
2.3.3 案例:自动提升
2.4 运算符
2.4.1 运算符分类
- 位操作运算符:位与(&)、位或(|)、位非(~)、位异或(^)、左移(<<)、右移(>>)
- 复合位运算赋值:&=、|=、^=、>>=、<<=
2.4.2 运算优先级
2.4.3 算术运算符
2.4.4 赋值运算符
2.4.5 位运算符
- 按位与运算符
- 按位或
- 按位异或
- 一次求反
- 向左移位
- 向右移位
2.4.6 比较运算符
2.4.7 逻辑运算符
2.4.8 逗号运算符
2.4.9 条件运算符
2.5 小结
第3章 控制语句
3.1 条件语句
3.1.1 if语句
3.1.2 案例:分支语句应用
3.1.3 switch语句
3.2 循环语句
3.2.1 while语句
3.2.2 do-while语句
3.2.3 for语句
3.2.4 案例:for语句应用
3.2.5 案例:嵌套循环
3.3 控制语句
3.3.1 break语句
3.3.2 continue语句
3.3.3 return语句
3.3.4 案例:使用goto语句
3.4 预处理命令
#import
#define
3.4.1 宏定义
- 1.无参数宏定义
- 2.带参数的宏定义
3.4.2 运算符
-
- "#"运算符
-
- "##"运算符
3.4.3 #import语句
- 1.#import与#include的联系和区别
- 2.#import与@Class的联系和区别
提高编译效率;
消除循环依赖关系;
3.4.4 条件编译
- 1.#if指令
- 2.#endif指令
- 3.#ifdef和#ifndef
- 4.#else指令
3.5 小结
第4章 C语言特性
- 一些应用程序为了优化会要求使用底层方法,如使用C语言的内置数据结构优化大型数据数组
4.1 数组(C语言)
- 基本数据类型的数组
4.1.1 定义数组
4.1.2 初始化数组
4.1.3 使用数组
- arrlength = sizeof(arr)/sizeof(arr[0])
4.1.4 定义多维数组
4.1.5 初始化多维数组
4.1.6 使用字符数组
4.1.7 案例实战
4.2 函数(C语言)
4.2.1 定义函数
4.2.2 声明函数
- 形参名可省略
4.2.3 函数类型
4.2.4 函数参数
4.2.5 函数返回值
4.2.6 案例实战
- 递归运算:如遍历未知深度路径下的所有文件
- 数组参数
4.3 块
4.3.1 定义块
^[块返回值类型](形参类型1 形参1,形参类型2 形参2,...)
{
// 块执行体
}
块返回值类型 (^块变量名)(形参类型1 形参1, 形参类型2 形参2,...) {
// 块执行体
}
5.2.3 self
- 哪些语言有self关键字?
- OC中的->运算符,运用场景之一:当局部变量和成员变量同名时,系统默认局部变量隐藏成员变量,为了消除这种隐藏关系,就可以使用self->来强调要使用的是成员变量
- 关于@property自动生成set/get方法与懒加载的关系:自动生成了set/get方法,也需要手动调用set方法才会给这个成员变量赋有意义的值,懒加载优化了赋值;平时使用的很多,靠的都是记忆,这次是加深了理解;
5.2.4
- id类型体现OC的动态绑定特性
- 想到OC中的@property到底是什么作用,每天都在用,为什么一定要用?不用的话有什么替代方案?
5.2.5 类名的使用
5.2.6 类的比较
5.3 变量
5.3.1 局部变量
5.3.2 全局变量
OC全局变量:1.extern 2.单例
全局变量会增加代码耦合度
5.3.3 实例变量
@private @protected @public @package
@public变量使对象无法隐藏它的数据,违背面向对象基本原则--将数据封装在对象中,防止被随意浏览和修改。尽量少用
5.3.4 静态变量
static也是常用的一个关键字,虽然有替代的方案(写在.m文件头部的静态常量,如cell的identifierID),但是不清楚使用static和成员变量的区别与适用场景
静态局部变量:函数内用static声明的
register关键字:寄存器,避免频繁读写内存
5.3.5 变量的存储类别
动态存储变量和静态存储变量
静态存储区会一直占有内存,直到运行结束才释放,包括全局变量和static修饰的局部变量
auto关键字:局部变量默认方式,自动存储机制,自动局部变量
静态变量与自动变量的一个区别是:系统是否会为其设置默认值
const:变量->常量
为什么static与const要一起使用?不使用static会怎样?
目前的理解是使用static会更加安全,将常量作用域限制在当前类中。
实验了一下:在两个.m文件中分别定义同一个不用static修饰的const常量,build时会报错
5.3.6 案例:定义单例类
5.3.7 案例:定义类变量
5.4 属性
@property
5.4.1 属性的声明
readonly修饰词
自己如何修改自定义的readonly属性,以及为何通过kvc尝试修改别人的readonly和禁止别人通过kvc在外部修改自己的readonly属性
关键方法:accessInstanceVariablesDirectly
5.4.2 属性的实现
@dynamic关键字
5.4.3 属性类型和相关函数
5.4.4 属性类型编码
5.4.5 属性重声明
可以在类扩展中把readonly重定义为readwrite
5.4.6 字类中的属性
5.4.7 案例:使用封装
封装、继承、多态
多态:没有继承就没有多态,父类指针可以指向字类对象,OC只有方法名多态
5.4.8 案例:使用访问控制符
5.4.9 案例:合成存取
@property
assign:不更改引用计数
atomic:原子操作,线程安全
readonly:只生成getter方法,不生成setter方法
unsafe_unretained:与weak类似,不如weak安全
copy:防止将可变字符串赋给字符串,导致字符串被随意篡改
5.4.10 案例:点语法存取
5.5 方法
5.5.1 定义方法
方法调用->传递消息
5.5.2 方法的所属性
OC传参机制:值传递,传入参数的副本,指针变量做参数,指针本身保存的是副本,所以相当于地址传递
5.5.3 案例:设计可变形参的方法
, ...
va_list、va_start、va_end、va_arg
个数可变的形参只能处于形参列表的最后,也就是说,一个方法最多只能有一个长度可变的形参
5.6 继承
树形结构
5.6.1 继承实例变量
5.6.2 方法的继承
5.6.3 方法的重写
5.6.4 类别和扩展
动态机制
Category必须引用类的接口文件,有.h和.m
Extension只有.h文件,常用于一个类除了公开声明的API外,再定义一些私有的方法
5.6.5 案例:类继承
OC摒弃了C++中的多继承特征
5.6.6 重写
5.6.7 案例:使用super关键字
子类重定义(在.m中)和父类完全相同的
5.7 异常处理
5.7.1 启用异常处理
5.7.2 异常处理
5.7.3 捕捉不同类型的异常
5.7.4 抛出异常
一般使用@throw抛出NSException对象,也可以抛出任何OC对象,只是NSException比较方便
5.8 类型
5.8.1 静态指定类型
5.8.2 类型的自查
5.9 根类
NSObject NSProxy
NSProxy被定义为抽象类,用于表示其他对象的替身对象。
5.9.1 NSObject简介
其他类通过从NSObject继承来访问OC语言运行时系统的基本接口。
NSObject协议
java.lang.Object Java版本的Cocoa
5.9.2 根类和协议
NSObject不仅是一个类的名称,还是一个协议的名称。
NSObject协议指定了OC中所有根类(包括NSProxy)必须有的基本编程接口。
5.9.3 根类方法
NSObject包含:NSObject协议和其他一些"根"协议,指定了通用的接口和行为
1.分配、初始化和复制
alloc:分配内存、指向运行时的类定义
init
new
2.对象的保持和清理
3.内省和比较
isSubclassOfClass:
类方法 instancesRespondToSelector:
4.对象的编码和解码
Coder编码器
NSCoder为抽象类,不能被实例化
自定义对象的归档
5.消息的转发
forwardInvocation:
6.消息的派发
performSelector 延迟派发,将消息从辅助线程派发到主线程
OC是一门动态语言
5.9.4 根类接口规范
5.9.5 根类实例方法和类方法
5.10 小结
6.消息和协议
OC的两大特色,使OC具有更强的灵活性和简洁性,同时保持了更高的扩展性和高内聚、低耦合的特性。
6.1 消息
OC与C++的区别:C++类与方法紧密结合,不能调用一个类中不存在的方法;OC中类与消息的关系较为松散,方法都视为对消息的回应,runtime时才会动态决定
6.1.1 定义消息
方法名在消息中通常被称为选择器
6.1.2 发送消息
行nil发送消息,是被允许的,运行时没有效果。
6.1.3 接收实例对象
6.1.4 获取方法地址
Cocoa运行时提供的功能:methodForSelector:,来避免动态绑定,将减少大部分消息的开销,但是这只有在指定的消息被重复发送很多次才有意义,
并不是OC语言本身的功能。
Cocoa:是Apple为Mac OS X所创建的原生面向对象的API,是Mac OS X上五大API之一,其他四个是Carbon、POSIX、X11、Java
6.1.5 objc_msgSend()函数
OC中,消息是直到运行时才和方法实现绑定的。
[reveiver message] -> objc_msgSend(receiver, selector)
编译器为类生成的结构,至少包含两个基本元素:
- 指向父类的指针
- 类的方法表,方法表将方法选标和方法实现的地址关联起来
isa:指向该对象的类结构的指针,从NSObject或NSProxy继承的对象都自动包括isa变量
为了加快消息的处理过程,运行时系统通常会将使用过的方法选标和方法实现的地址放入缓存中,每个类都有一个独立的缓存,同时包括继承的方法和在该类中定义的方法。
6.1.6 使用隐藏的参数
6.1.7 消息转发
forwardInvocation:消息
对象无法处理一条消息时,运行时会在抛出错误前发送该消息。
实现forwardInvocation:方法对不能处理的消息进行一些默认处理,或者将消息转发给其他对象。
场景1:设计一个能够响应某消息的对象,并且包括其他类型对象对消息的响应。
场景2:希望一个对象能和另一个类的对象都某消息的响应完全一致,且这两个类不在同一个继承链中。
invokeWithTarget:方法来转发
6.1.8 消息转发与多重继承
转发消息的对象看起来有两个继承体系,自己的和响应消息的对象的。
只是能够模拟多继承的特性,本质上还是不同,多继承可能会导致庞大的,复杂的对象,消息转发不会。
6.1.9 消息代理对象
6.1.10 消息转发与类继承
respondsToSelector:只能出现在继承链中,不能出现在消息转发链中。
如果希望代理对象看起来就像继承自它代表的对象一样,需要重新实现respondsToSelector:、isKindOfClass:、instancesRespondToSelector:、conformsToProtocol:等方法。
methodSignatureForSelector:方法必须能返回实际响应消息的方法的描述。
6.1.11 多态性
不同的对象可以对同一个消息做出不同的响应。
6.1.12 动态绑定
C的方法调用:编译时确定绑定关系
OC的发送消息:运行时确定
6.1.13 解析动态方法
resolveInstanceMethod:和resolveClassMethod:动态实现@dynamic.
OC方法可以认为是至少有两个参数(self和_cmd)的C函数。
消息转发和动态方法解析是互不相干的,动态方法解析时机更前。
6.1.14 动态加载
OC在运行时链接和载入新的类和范畴类。
NSBundle类为动态加载提供了一个更方便的接口。
6.1.15 "."语法格式
好处之一:点语法可以在试图修改只读属性时报错,使用[ ]语法只会出现警告,运行时才失败。
6.1.15.1 "."语法格式一般用法
6.1.15.2 nil值
6.1.15.3 点语法引用访问方法
6.1.15.4 点语法的错误用法
6.1.15.5 性能和线程处理
使用点语法不会引入额外的线程开销。
6.2 协议
非正式协议与编译器保证的正式协议
6.2.1 预定义声明接口
Cocoa大量使用协议来实现通过OC消息进行进程间的通信。
6.2.2 预定义方法
用协议来为未定义的类规定接受特定消息的能力。
6.2.3 声明接口
协议使匿名对象成为可能,没有协议,就没有办法声明一个对象的接口而不指明它的类。
6.2.4 非层级相似性
用抽象类继承的方法来为共通方法分组是不可行的,有时一些不相关的类却要实现一些相似的方法,而有限的相似之处又不足以建立一种继承的关系。协议可以实现。
6.2.5 正式协议
编译器可以基于协议进行类型校验。
6.2.5.1 声明一个协议
类名有全局可见的属性,协议名没有全局可见属性,只能存在于自己的命名空间。
6.2.5.2 可选的协议方法
默认为@required.
协议的继承和类继承不一样,协议完全支持多继承。
6.2.6 非正式协议
类别或类扩展。
正式协议:只声明不实现;
非正式协议:既声明又实现;
6.2.7 协议对象
正式协议也是由协议类的实例所表现的。和类对象一样,协议对象也是由系统在运行时使用代码中定义的方法和声明的变量来创建,都不在程序的源代码中分配内存和初始化。
源代码中可以用@protocol()引用一个协议对象。
只有在协议被类遵守或使用@protocol()时编译器才会创建协议对象。
6.2.8 采用协议
分类中也可以使用协议。
6.2.9 服从协议
conformsToProtocol:
之前几年自己开发过程中用的比较多的协议和代理绑定使用,单纯的协议用的少,导致在B站代码中有不熟悉的使用方式,其实原理都很简单。
6.2.10 类型校验
id<协议名>对象名
6.2.11 嵌套协议
6.2.12 引用其他协议
6.3 小结
OC两大特色:消息和协议
7.对象
对象->类的实例。
面向对象程序是围绕着对象建立起来的。
对象的状态->表示对象的实例变量
对象的方法->对象的操作性,操作对象的状态
对象 -> 编程单元 -> 数结构(实例变量) + 一组程序(方法)
7.1 创建对象
创建对象的两个阶段:对象分配 + 初始化。
初始化总是紧跟对象分配,但这两个步骤的作用是不同的。
7.1.1 分配对象
为对象分配足够的内存。
其他重要工作:
- 对象计数器置为1
- 使对象的isa指向类,类是根据类定义编译得到的运行时对象
- 将对象的所有实例变量初始化为0或与0等价的类型
7.1.2 初始化对象
7.1.2.1 对象初始化实现
init方法。
自定义初始化方法唯一的要求是必须以init开头。
iOS的多参数方法规则:第一个和最重要的参数之前使用Withxx:或Fromxx:.
7.1.2.2 初始化方法
初始化可能失败,返回nil,使用前需要校验。
7.1.2.3 实现一个初始化方法
7.1.2.4 多个初始化方法和指定初始化方法
辅助初始化方法:其内部需要调用指定的初始化方法,为没有显式要求的参数传入默认值。防止没有被完全初始化。确保所有继承到的初始化方法都被覆盖是很重要的。
指定初始化方法:覆盖面最大的初始化方法,也负责通过向super发送消息来调用父类中的指定初始化方法。
7.1.3 delloc方法
确保对象的实例变量被释放,并确保动态分配的内存被释放。
init方法先调用父类初始化方法,delloc方法最后调用父类方法。
7.1.4 类工厂方法
将分配和初始化合在一起,并进行自动释放处理。
工厂类的优势之一:init必须先分配一个对象,工厂方法可以避免生成用不到的对象,不会盲目生成对象。
7.2 对象动态类型
id、nil和其他OC基础类型都是在objc/objc.h中定义的。
id被定义为一个对象数据结构的指针。
isa变量:表示对象是哪个类的实例
7.3 对象可变性
7.3.1 可变或不可变对象
7.3.2 用可变对象编程
7.3.2.1 创建和转换可变对象
7.3.2.2 存储和返回可变实例变量
7.3.2.3 接收可变对象
7.3.2.4 集合中的可变对象
7.4 对象通信
实现对象间的通信机制的几个设计模式:委托、通知、目标-动作、绑定技术
7.4.1 面向对象程序中的通信
程序中的对象还动态地存在于一个网络中,与管弦乐队中的音乐家之间的合作方式类似,程序中的每个对象都有一个角色,为了在程序中发挥作用,角色必须能够和其他对象进行通信。
7.4.2 IBOutlet变量
xib相关原理。
IBOutlet对象的引用是有Interface Builder来配置和归档的。每次包含对象从nib文件解档时,其与插座变量之间的连接都需要重新建立。
7.4.3 委托和数据源
7.4.3.1 委托
非正式协议的方法标志着进行任务委托的对象需要处理或预期发生的重大事件。
委托处理的事用户界面的控制,而数据源处理的是对数据的控制。
7.4.4 目标-动作机制
7.4.4.1 控件、单元和菜单项
7.4.4.2 目标
7.4.4.3 动作
7.4.4.4 Application Kit定义的动作
7.4.4.5 设置目标和动作
7.4.5 绑定
7.4.5.1 绑定的工作机制
7.4.5.2 创建绑定
7.4.6 通告
代理:一对一
通知:一对多
通知中心
7.4.6.1 通告对象
7.4.6.2 通知中心
7.4.6.3 通知队列
先进先出FIFO的顺序维护通知,每个线程都有一个默认的通知队列。
7.4.6.4 通知队列发送模式
尽快发送、空闲时发送、立即发送
7.5 使用对象
7.5.1 对象所有权策略
7.5.2 保留计数
7.5.3 自动释放
7.5.4 共享对象的有效性
7.5.5 存取方法
7.5.6 回收对象
7.5.7 通过引用返回的对象
7.6 小结
8.Foundation框架基础
8.1 认识Foundation框架
值对象
NSValue和NSNumber类为简单的标量值数组提供面向对象的存储空间。字符串
集合
操作系统服务
NSProcessInfo:查询运行环境
NSHost:主机系统在网络中的名称和地址
NSTimer
NSRunLoop
NSUserDefaults文件系统和URL
NSFileManager
NSFileHandle:较为底层的文件操作,如文件内查找操作
NSBundle:寻找储存在程序包中的资源
NSURL和NSURLHandle进程间通信
NSPipe线程和子任务
NSThread
NSTask:程序可以分出一个子进程来执行其他工作或进行进度监控归档和序列化
NSCoder
NSCoding协议表达式和条件判断
NSPredicate 谓词
NSCompoundPredicate
NSComparisonPredicate
NSExpressionSpotlight(聚光灯)查询
NSMetadataItem
NSMetadataQuery
查询元数据OC语言服务
NSException 例外
NSAssertionHandler 断言
NSInvocation
NSMethodSignature
NSClassDescription脚本
分布式对象
NSDistantObject
NSProtocolChecker
根类是NSProxy网络
NSNetService
NSNetSerciceBorwser
Bonjour系统提示
Foundation框架:OC接口
Core Foundation框架:C语言接口
Toll-free bridging
8.2 使用Foundation框架
8.3 数字类型
NSNumber是NSValue的子类
8.3.1 数字类型类NSNumber
数字对象的声明、创建、初始化、转换等
8.3.1.1 数字对象的声明
任何数字对象都可以用NSNumber来声明。
8.3.1.2 数字对象的创建
每个基本数字类型,都有一个对应的类方法。
numberWith开头,
numberWithLong: numberWithFloat:等
8.3.1.3 数字对象的初始化
实例方法initWithLong: initWithFloat:等。
类方法---实例方法---检索方法
8.3.2 比较int、NSInteger、NSUInteger和NSNumber
NSInteger:不用考虑设备是32位还是64位的。
NSArray:存放是对象,不能存放基础类型。
8.4 字符串类型
8.4.1 不可变字符串类NSString
8.4.1.1 不可变字符串的创建
NSString是一个对象,char *是一个字节数组。
8.4.1.2 不可变字符串的遍历
8.4.1.3 不可变字符串的比较
8.4.2 可变字符串类NSMutableString
8.4.2.1 可变字符串的创建
8.4.2.2 可变字符串的增删
字符串的大小并不仅限于所提供的容量,仅仅是一个最优结构。
8.4.2.3 可变字符串的替换
8.4.3 案例实战
OC的字符串处理比C语言简单、易用。
8.5 日期类型
Time Interval(间隔):秒级别
8.5.1 日期类型类NSDate
- 创建和初始化
- 日期比较
- 时间间隔处理
8.5.1.1 创建日期
类方法[NSDate date]等价于[[NSDate alloc] init].
8.5.1.2 日期与字符串的转换
NSDateFormatter
8.5.1.3 获取日期各个部分整数值
dateWithCalendarFormat:
yearOfCommonEra、monthOfYear、dayOfMonth、dayOfWeek等
8.5.2 NSCalendar和NSDateComponents
656
8.5.3 案例实战
8.6 数组类型
8.6.1 不可变数组类NSArray
8.6.1.1 不可变数组的创建
8.6.1.2 不可变数组的遍历
8.6.1.3 不可变数组的复制
8.6.1.4 不可变数组的排序
8.6.2 可变数组类NSMutableArray
8.6.2.1 可变数组的初始化
8.6.2.2 可变数组的增删
8.6.2.3 可变数组的替换
8.6.3 多维数组
8.6.4 案例:操作数组
8.6.5 案例:操作元素
makeObjectsPerformSelector: 调用数组中每个元素的指定方法。
enumerateObjectsUsingBlock:遍历集合中所有元素,并依次使用元素执行指定的代码块。
684
8.6.6 案例:数组排序
sort排序函数
ordered 组织有序的;descend 下降;ascend上升
NSOrderedDescending等等。usingFunction:context:
usingSelector:
usingComparator:
NSString的compare:方法
8.6.7 案例:遍历数组
reverse 颠倒
objectEnumerator: 或 reverseObjectEnumerator:方法
8.6.8 案例:快速枚举
foreach循环 概念
8.6.9 案例:可变数组
692
8.7 字典类型
8.7.1 不可变字典类NSDictionary
8.7.1.1 不可变字典的创建
8.7.1.2 不可变字典的查询
8.7.2 可变字典类NSMutableDictionary
8.7.2.1 可变字典的创建
8.7.2.2 可变字典的添加
8.7.2.3 可变字典的删除
8.7.3 案例:使用字典
8.7.4 案例:字典排序
keysSortedByValueUsingSelector:
keysSortedByValueUsingComparator:
keysSortedByValueWithOptions:
8.7.5 案例:字典过滤
keysOfEntriesPassingTest:
keysOfEntriesWithOptions:passingTest:
8.7.6 案例:使用可变字典
8.8 案例实战:集合类型
NSArray--有序、可重复,元素可以是基本类型,有索引
NSSet--无序、不可重复,元素只能是对象,无索引
NSOrderedSet--有序、不可重复,有索引
NSDictionary--具有映射关系
8.8.1 使用NSSet
NSSet没有索引,不能根据索引来操作元素。
和NSArray的共同点:
- count方法
- for-in快速枚举
- objectEnumerator方法
- makeObjectsPerformSelector: 方法等
- valueForKey: 和 setValue:forKey:进行KVC编程
- KVO编程
NSSet自有方法:
- setByAddingObject:等几个添加元素方法
- allObject: 返回数组
- anyObject: 返回某个不确定元素
- containsObject: 是否包含
- member:
- objectsPassingTest: 过滤
- isSubsetOfSet: 是否是另一个集合的子集合
- intersectsSet: 两个集合是否有交集
8.8.2 检测NSSet重复值
存入元素前,会先比较hashCode是否相同,不相同就是新元素,存入成功;相同的话会接着比较isEqual:,不相同会存在底层Hash表同一个位置,将这个位置形成链,相同则添加失败。
8.8.3 可变集合
NSMutableSet
unionSet:计算两集合并集
minusSet: 计算两集合差集
8.8.4 计数集合
NSCountedSet 是 NSMutableSet 的子类。
为每个元素额外维护一个添加次数的状态。类似于内存管理机制的引用次数。
8.8.5 有序集合
NSOrderedSet于NSMutableOrderedSet
8.9 小结
722
9 iOS应用开发核心
9.1 iOS应用架构
UIApplication对象:从系统接收事件
9.1.1 生命周期
程序启动到终止期间。
进入app后,大量初始化工作就交给UIKit,事件循环。
9.1.2 主函数
Main函数:
- 创建自动释放池
- 调用UIApplicationMain()函数
- 使用自动释放池
UIApplicationMain()的四个参数:
- argc,C语言概念,发送给main函数的命令行参数的个数
- argv,C语言概念,存放只想字符串参数的指针
- 首要类,为nil时,UIKit默认使用UIApplication类
- 应用委托类,一般为AppDelegate
9.1.3 应用委托
委托是一种避免对复杂的UIKit对象(如UIApplication对象)进行子类化的机制。避免对复杂对象进行修改。
负责处理几个关键的系统消息。
遵循UIApplicationDelegate协议。
9.1.4 nib文件
用户储存可在应用程序需要时使用的一些“冻结”的对象。
将nib文件载入应用程序时,nib装载代码会将文件中的内容转换为应用程序可以操作的真正对象。
通过这个机制,nib文件省去了用代码创建这些对象的工作。
Interface Builder:是一个可视化的设计环境,可以用来创建nib.
9.1.5 事件处理周期
UIEvent:事件对象。
UITouch:触摸对象,对应一个手指。
系统发送的触摸事件会在队列中等待,知道被应用程序的主运行循环处理。
9.1.6 基本设置模式
9.2 运行环境处理机制
快速而安全。
9.2.1 快速启动
每次只有一个前台应用,所以程序必须快速启动和初始化,以尽可能减少延迟,否则会为用户带来不好的体验。
退出时,需要尽快将未保存的修改保存到磁盘上,如果超过5秒,系统会立刻终止程序运行。
9.2.2 安全处理
沙盒可以限制攻击者对其他程序和系统造成的破坏,但是不能防止攻击的发生,不能使程序避免恶意的直接攻击。
如在输入处理代码中有一个可利用的缓冲区溢出,而又没有对用户输入进行正当性检查,则黑客可能会通过这种漏洞来执行代码。
9.2.3 内存处理
iOS与Mac OS X都使用虚拟内存系统。
内存释放:释放没有在使用的内存页面->向正在运行的程序发出释放内存的通告。
9.2.4 节电处理
自动休眠定时器。
游戏或其他特定应用可以禁用该定时器。
737
9.3 程序包
[NSBundle mainBundle]用于返回一个代表程序包的对象。
9.3.1 信息属性
Info.plist
Show Raw Keys/Values
9.3.2 程序图标和启动图像
9.4 定制行为
9.4.1 景观模式启动
横屏or竖屏显示。
9.4.2 与其他程序通信
openURL:
9.4.3 URL模式
可以在Safari中输入定制的URL来确定是否可以启动app.
9.4.4 处理URL请求
application:handleOpenURL:
9.4.5 偏好设置
9.4.6 关闭锁定
9.5 键盘管理
9.5.1 接收键盘通知
键盘焦点变化时。会发送UIKeyboardWillHideNotification通知当前键盘所有者即将失去焦点,不会发送UIKeyboardDidHideNotification通知。
键盘方向改变时,UIKeyboardWillHideNotification和UIKeyboardDidHideNotification通知都会发出,因为不同方向的键盘是不同的。
键盘通知包含键盘在屏幕上的位置和尺寸。
9.5.2 显示键盘
调用becomeFirstResponder方法与点击视图使其成为第一响应者效果一致。
9.5.3 取消键盘
9.5.4 移动键盘
UIScrollView类的scrollRectToVisible:animated:方法将被单击的文本框滚动到视图中。
keyboardWasShown:
9.6 国际化
9.7 优化处理
9.7.1 不要阻塞主线程
主线程阻塞,可能影响程序的正常启动和退出。导致意外的bug.
9.7.2 有效使用内存
把减少应用程序的内存开销放在较高优先级上,及时清除自己使用的内存。
9.7.3 减少内存印迹
- 消除内存泄漏
- 尽量减小资源文件
- 使用数据库处理大的数据集合
- 谨慎预载入,真正需要预载入时才进行操作,否则会浪费内存
9.7.4 恰当分配内存
9.7.5 浮点计算
典型情况下,基于硬件的浮点数计算比对应的基于软件的定点数计算快得多。
9.7.6 减少电力消耗
提高电池寿命。
原则:
- 避免需要轮询的工作,这样会组织CPU进入休眠状态,可以通过NSRunLoop或NSTimer来规划工作。
- idleTimerDisabled属性保持为NO.
- 将任务合并在一起,使空闲时间最大化,间歇性执行任务比一次性完成相同数量的任务消耗更多电能,也会阻止系统长时间无法关闭硬件。
- 避免过度访问磁盘。
访问网络的耗电量。
传递的数据越多,就需要越多的电能来进行无线发射。访问网络是所能进行的最耗电操作。
网络访问原则:
- 需要时再连接网络,不对服务器进行轮询。
- 使用紧凑的数据格式,不要包含可被忽略的额外数据。
- 尽可能以群发方式传递数据包。
- Wi-Fi耗电比系带无线少。
- 使用Core Location定位服务时,设置恰当的精度和过滤器的值,及时关闭硬件。
722
9.7.7 代码优化
优化工具:
- 消除内存泄漏
- 排除代码中可能由低效算法或已知瓶颈引起的计算热点
Instruments程序
模拟器与真机差别:模拟器运行在Mac OS X 上,具有更快的CPU和更多的可用内存,比真机性能好很多,所以尽量用真机,更可能发现额外的性能瓶颈。
9.8 小结
10 iOS开发入门
10.1 熟悉iOS项目
10.1.1 文件结构
InfoPlist.strings--国际化支持文件
10.1.1.1 Test文件夹
10.1.1.2 TestTests文件夹
10.1.1.3 Products文件夹
.app文件所在
10.1.2 新建xib界面文件
替换storyboard为xib文件过程。
10.1.3 认识xib界面
- Placeholder列表区
- Objects列表区
.xib与.nib的区别:
- .xib是XML文件,.nib是二进制格式文件。
- 编译时,会将.xib转换为.nib,不存在性能差别。
- 开发者使用.xib更方便,因为是文本文件,容易比较和版本控制。
10.1.4 添加控件
Control+Option+Command + 数字:打开不同的库面板。
Editor->Canvas->Show Layout Rectangles:显示UI控件轮廓。
10.1.5 编辑控件属性
右边功能区域:
- 文件检查器面板
- 操作历史面板
- 快速帮助
- 身份检查
- 属性检查
- 大小检查
- 连接检查
Label的属性检查面板:
- Label支持的属性
- 父类View支持的属性
10.1.6 UIView属性
10.1.6.1 Mode
图片对齐方式、是否缩放。
缩放选项会带来额外的处理开销。
10.1.6.2 Tag
10.1.6.3 Interaction
- UserInterfaceENable--是否可点
- Multiple Touch--是否支持多点触摸
10.1.6.4 Alpha
10.1.6.5 Background
10.1.6.6 Drawing
Opaque--不透明,通知iOS系统,该控件后面的任何内容都无须绘制,即使Alpha值小于1.0,使程序保持好性能。
Hidden
Clears Graphics Context--先清除该控件所覆盖的区域,再开始绘制该控件,系统执行额外的清除操作,性能会降低。
Clip Subviews
Autoresize Subviews
10.1.6.7 Streching
拉伸区域。
800
10.1.7 UILabel属性
10.1.7.1 Text
10.1.7.2 Color
10.1.7.3 Font
10.1.7.4 Alignment
10.1.7.5 Lines
10.1.7.6 Behavior
10.1.7.7 Line Break
10.1.7.8 Autoshrink
自动收缩
10.1.7.9 Highlighted
10.1.7.10 Shadow
10.1.7.11 Shadow Offset
10.2 iOS运行机制
10.2.1 了解MVC
10.2.2 入口函数
Main函数负责生成UIApplication对象。
10.2.3 应用程序委托
UIApplication对象->代表整个iOS应用程序本身,为全局对象。
AppDelegate是UIApplication的代理,是整个iOS应用的通信中心。
获取AppDelegate对象方法:
AppDelegate *appDelegate = [UIApplication shareApplication].delegate ;
AppDelegate继承自UIResponder类,遵守UIApplicationDelegate协议。
10.2.4 视图控制器
UIViewController
viewWillLayoutSubviews:
viewDidLayoutSubviews:
10.3 事件处理机制
10.3.1 获取控件
10.3.1.1 通过IBOutlet属性获取控件
10.3.1.2 通过Tag属性获取控件
10.3.2 事件处理
10.3.2.1 通过IBAction绑定事件
通过xib拉线方式创建事件。
10.3.2.2 通过代码设置事件
10.3.2.3 通过委托对象设置事件
10.4 故事板
Storyboard与xib区别:
- SB的dock区域多了一个场景Scene的概念
Scene = view + vc + 第一响应者
10.5 案例实战
862
10.5.1 动态更新文本
纯代码开发并不是最好的方式,原因:
- 步骤繁琐
- 不符合MVC设计原则,不利于组件解耦
10.5.2 添加和删除控件
10.5.3 设计跟随手指的小球
UIView子类可以重写的方法:
initWithCoder: nib文件中加载完控件后会自动调用该方法。
didAddSubview: 添加子控件后调用。
willRemoveSubView: 将要删除子控件时。
willMoveToSuperview: 控件将要添加到父视图中时。
didMoveToSuperView:
willMoveToWindow:
didMoveToWindow:
10.5.4 设计应用项目图标
10.5.5 设计欢迎界面
10.6 小结
11 窗口和视图
11.1 认识窗口和视图
11.1.1 窗口
Window在Mac OS X与iOS的区别:
- NSWindow的父类是NSResponder
- UIWindow的父类是UIView
11.1.2 视图
1.1.2.1 描画和动画
1.1.2.2 布局和子视图管理
1.1.2.3 事件处理
11.1.3 视图控制器
11.2 视图架构
11.2.1 视图交互模型
11.2.2 视图渲染架构
Core Animation(CALayer类的实例):
- 在Mac OS X上是可选的。
- 在iOS上是视图渲染实现的核心。
当UIView类没有提供需要的接口时,就可以深入到Core Animation层,实现一些复杂的渲染。
11.2.3 CoreAnimation
CoreAnimation利用硬件加速和架构上的优化来实现快速渲染和实时动画。
会捕捉首次绘制后的信息到位图中,方便后续重用。
层树:存储和View对象相关联的Layer.两组层树,表示树和渲染树。
11.2.3 视图的层
layerClass类方法:可以重载View的Layer类型。通常用在基于OpenGL的app中。
11.2.5 动画支持
UIView支持动画的属性:frame、bounds、center、transform和alpha.
11.2.6 视图坐标系统
11.2.7 边框、边界和中心
900
11.2.8 坐标系统变换
11.2.9 内容模式与比例缩放
11.2.10 自动尺寸调整
11.3 创建和管理视图层次
11.3.1 视图层次
11.3.2 创建视图对象
11.3.3 添加和移除子视图
isDescendantOfView: 是否包含某个view
11.3.4 坐标转换
11.3.5 标识视图
11.4 动态控制视图
11.4.1 实现视图动画
11.4.2 配置动画的参数
setAnimationRepeatCount: 动画重复次数。
setAnimationRepeatAutoreverses: 自动反向播放。
setAnimationBeginsFromCurrentState: 使动画线程中的动画停止,立即启动新动画。
setAnimationsEnabled: 是否激活动画。
动画线程。
11.4.3 配置动画的委托
setAnimationDelegate:方法设置代理。
11.4.4 响应布局的变化
layoutSubviews:
11.4.5 重画视图的内容
setNeedDisplay:
setNeedDisplayInRect:
drawRect:
11.4.6 隐藏视图
11.5 创建定制视图
11.5.1 初始化定制视图
11.5.2 描画视图内容
clearsContextBeforeDrawing: 提高描画性能。
11.5.3 响应事件
hitTest:withEvent:
pointInside:withEvent:
11.5.4 清理视图对象
11.6 小结
930
12 视图控制器
12.1 视图控制器基础
12.1.1 视图控制器的功能
12.1.2 屏幕、窗口和视图元素
12.1.3 视图管理机制
12.1.4 视图控制器分类
UIViewController的子类分为:
- 内容类视图控制器
- 容器类视图控制器
12.1.5 内容展示方式
12.1.6 视图控制器混合应用
12.2 视图控制器生命周期
12.2.1 初始化视图
12.2.1.1 xib创建VC
xib把vc保存为一个XML文件。
12.2.2 加载和卸载视图
12.2.2.1 视图控制器加载周期
viewDidLoad方法调用前的逻辑流程,保证view一定有值。
loadView方法:重写时不需要调用父类super方法。
12.2.2.2 vc卸载周期
viewWillUnload方法:开发过程中还没接触过。
12.3 标准视图控制器
UIViewController
12.3.1 UIViewController概述
12.3.2 使用标准视图控制器
12.4 SplitViewController
iPad专属。
12.4.1 SplitViewController概述
12.4.2 使用SplitViewController
12.5 导航控制器
NavigationController
12.5.1 NavigationController概述
12.5.2 使用NavigationController
12.6 TabBarController
12.6.1 概述
12.6.2 使用
12.7 PageViewController
12.7.1 概述
翻页效果。
12.7.2 使用
12.8 小结
986
13 事件
UIEvent
- 触摸事件
- 运动事件
13.1 触摸事件
基于多点触摸。
13.1.1 触摸模型
多点触摸序列,序列元素为:触摸特征=位置+触摸时间。
手指接触区域:大致是椭圆的,比想象的位置更靠下,底层的多点触摸系统会分析这些信息,计算出单一的触点。
13.1.2 触摸与事件
触摸信息:时间 和 空间
时间方面:阶段(phrase)
UITouch : 触摸
UIEvent : 事件
事件的取消可能是由于重载系统事件引起的,如电话呼入。
13.1.3 事件传递
事件队列。
sendEvent : UIApplication对象和UIWindow对象派发事件的方法。
exclusiveTouch 独占触摸属性。
13.1.4 事件响应过程
UIResponder :所有响应者对象的基类。
13.1.5 事件处理方法
UIResponder 声明的一些方法:
touchesBegan:
touchesMoved:
locationInView: 当前位置
previousLocationInView: 前一个位置
跟踪UITouch对象的变化:
可以以UITouch对象的地址作为键,位置作为值,存储在CFDictionaryRef类型中。
CFDictionaryRef与NSDictionary的区别:
NSDictionary需要对存储项目进行复制,存储内容需要遵守NSCoping协议;CFDictionaryRef不需要这些,;UITouch不遵守NSCoping,所以应选用CFDictionaryRef.
13.1.6 案例:处理多点触摸事件
判断是两次独立的单击还是一次双击。
13.1.7 案例:检测碰擦收拾
swipe
13.1.8 案例:处理复杂多点触摸序列
1007
13.2 运动事件
如摇摆设备。
motionBegan:withEvent:
motionEnded:withEvent:
motionCancelled:withEvent:
13.3 复制、剪切和粘贴
UIMenuController类:显示编辑菜单
UIResponder类: canPerformAction:withSender:
UIResponderStandardEditActions非正式协议
13.3.1 认识粘贴板
可通过定制URL类型传输数据。
公共
私有:自己创建,设置persistent为yes,可在程序退出后继续存在。
UIPastedboardNameGeneral : 剪切、复制和粘贴。
UIPastedboardNameFind : 检索操作。
可以有一个或多个数据项。
13.3.2 数据表示
同一个数据项的多种表示。
UTI : 某种表示的唯一类型标识符。
粘贴板读取程序必须找到最适合自身能力的数据类型。
变化计数:随着粘贴板内容的变化而递增。
13.3.3 选择菜单
多选操作。
13.3.4 复制和剪切
13.3.5 粘贴
13.3.6 消除菜单
13.4 小结
14 使用空间(上)
友好的图形用户界面,是吸引用户的关键。
UIView:定义了视图的基本行为,但不定义视图的视觉表示。
UIKit:定义了具体的视觉外观和行为,提供了大量标准界面元素。
14.1 UIKit 概述
14.1.1 视图分类
- 控件:UIControl子类
- 窗口:UIWindow
- 容器视图
- 显示视图
- 文本和Web视图
- 导航视图
- 警告框和操作表
14.1.2 应用界面构成
14.1.3 UIView视图
UIView:继承自UIResponder
14.1.4 UIControl控件
1033
14.2 按钮
14.2.1 添加按钮
14.2.2 案例:定义按钮
14.2.3 案例:配合使用标签和按钮
14.3 UITextField
14.4 UITextView
14.5 UISwitch
14.6 UISegmentedControl
14.7 UISlider
14.8 UIImageView
animationImages属性播放幻灯片。
14.9 UIProgressView
14.10 UIActivityIndicatorView
14.11 UIAlertView
14.12 UIActionSheet
14.13 UIDatePicker
14.14 UIPickerView
14.15 UIStepper 微调器
14.16 UIWebView
14.17 小结
15 使用控件(下)
15.1 UIToolBar
15.2 UISearchBar
15.3 导航条
15.4 UITableView
15.5 UITabBarController
15.6 UIPageControl
15.7 小结
1350
16 移动绘图
- OpenGL
- Quartz 2D、Core Animation、UIKit
16.1 基本概念
绘制都发生在UIView对象区域内。
16.1.1 绘制周期
触发drawRect:的几个场景。
16.1.2 坐标系统
CTM:转换矩阵,是一个数学矩阵,可以修改默认的坐标系统。也会降低创建路径的开销。
16.1.3 图形上下文
16.1.4 点和像素
16.1.5 颜色空间
CGContextSetRGBStrokeColor()
CGContextSetRGBFillColor()
16.1.6 图像格式
.tiff、.bmp、.ico、.cur、.xbm
16.1.7 定制绘制
沉浸式应用:广泛使用定制的绘制代码;
工具型和效率型:使用标准的视图和控件显示内容就可以。
16.1.8 绘制性能
绘制的开销比较昂贵。
优化绘制代码的方法:
- 最小化
- 标识为不透明
- 删除PNG中的Alpha通道
- 避免清除原先内容
等
16.1.9 图像质量
- PNG:iOS对PNG的绘制路径经过优化。
- 避免调整尺寸,减小CPU开销。
16.2 Quartz 2D
高级二维绘图引擎。
16.2.1 页面
page:叠加更多绘画,不同的绘制顺序所产生的效果不一样。
16.2.2 图形上下文
GraphicsContext:CGContextRef数据类型。包含所有与设备相关的特性,不需要任何设备相关的计算,都由Quart完成。
UIKit与Quartz坐标系统不同,使用CTM转换。
1368
16.2.3 路径
2D几何形状。
UIRectFrame()和UIRectFill()创建矩形简单路径。
shapes subpath
16.2.3.1 路径的创建
16.2.3.2 构建块
点、线、弧、曲线
关闭子路径:会添加一条线,线、弧和曲线通常不会关闭路径。
16.2.3.3 路径的创建和绘制
BeginPath()、MoveToPoint()
可复用路径:CGPathRef、CGMutablePathRef
16.2.3.4 颜色空间
Quartz重的颜色用一组值来表示,颜色空间用于解析这些信息。如RGB、HSB、BGR.
16.2.5 变换
Quartz 2D定义了两种独立的坐标空间:用户空间和设备空间。用户空间用浮点数表示坐标,与设备空间的像素分辨路没有关系。
CTM修改用户空间。
变换矩阵函数。
CGContextDrawImage()
16.2.5.1 平移变换
CGContextTranslateCTM()
16.2.5.2 旋转变换
CGContextRotateCTM()
弧度与角度转换函数。
16.2.5.3 缩放变换
CGContextScaleCTM(),负数可以倒转坐标轴。
16.2.5.4 联合变换
CGContextConcatCTM()
16.2.6 阴影
xy偏移量、模糊值(blur)
16.2.6.1 阴影形成原理
RGB中默认是黑色且透明度为1/3。
CGContextSetShadowWithColor()
16.2.6.2 绘制阴影
关闭阴影:恢复图形状态或颜色为NULL。
16.2.7 梯度
渐变:CGShadingRef和CGGradientRef,可以创建轴向或径向渐变。
16.2.7.1 轴向和径向渐变展示
16.2.7.2 CGGradient使用
CGGradient对象比CGShading对象更容易重用。因为没有存储几何形状,允许使用相同的颜色方案来绘制不同的几何图形。
16.2.7.3 CGShading对象的使用
1396
16.2.8 透明层
TransparencyLayers
通过组合两个或多个对象来生成组合图形。
16.2.8.1 工作机制
Quartz为每个上下文维护一个透明层栈。
绘制完成后,Quartz将结合对象放入上下文,并使用上下文的全局Alpha值、阴影状态已裁减区域用于组合对象。
16.2.8.2 透明层中进行绘制
几个函数。
16.2.9 使用PDF文档
16.2.9.1 打开查看PDF
CGPDFDocumentRef数据类型。
16.2.9.2 为PDF页创建一个转换
16.2.9.3 创建PDF文件
16.2.9.4 添加链接
16.2.9.5 保护PDF内容
16.3 案例实战
16.3.1 案例:绘制图形
16.3.2 案例:绘制线条
16.3.3 案例:绘制文本
CGContextRef.
16.3.4 案例:绘制路径
CGContextAddStar()可以画五角星和三角形。
16.3.5 案例:绘制曲线
curve:曲线
quad curve:四边形曲线
二元曲线:开始点、结束点、控制点
16.3.6 案例:设计画板
16.4 小结
17 动画设计
OpenGL是一个跨平台的、基于C语言的接口,可创建2D和3D内容。
Core Animation 是一个用于图形渲染、投影和动画OC类集合,使创建动画的难度降低。
1447
17.1 OpenGL ES
是OpenGL的嵌入式系统版本,精简版本,专门为移动设备设计。
适用于游戏或高帧率应用。
17.1.1 OpenGL ES概述
OpenGL ES 1.x 是针对固定管线硬件的。
OpenGL ES 2.x 针对可编程管线硬件。
被广泛推广的原因:
- 行业标准和免税版。
- 占用空间小和低耗能。嵌入式优势。
- 从软件到硬件渲染的无缝连接。用于更高耗能设备的硬件加速。
- 可扩展和演变。
- 使用简单。
- 文件管理有序。
17.1.2 配置上下文
上下文可以把每一种实现的状况信息封装在一起,容易使多个应用共享图形硬件,而不会干扰彼此的状况。
EAGLContext对象。
17.1.2.1 上下文在线程中的配置
setCurrentContext:设置新的上下文时,会释放以前的上下文。
17.1.2.2 上下文和OpenGL ES版本
pipeline 来源于福特生产车间的流水线作业。
判断初始化是否成功。
17.1.3 OpenGL ES绘制
创建帧缓存->渲染成影像
17.1.3.1 帧缓存的对象存储渲染结果
framebuffer
测试帧缓存的完整性。
renderbuffer 屏幕外的图像处理。
17.1.3.2 离屏帧缓存对象
GLuint;
glGenFramebuffers;
glBindFramebuffer;
glRenderbufferStorage;
17.1.3.3 绘制到一个帧缓存对象
填充帧缓存对象。
17.2 OpenGL ES 应用
17.2.1 项目的创建和设置
17.2.2 上下文的创建
EAGLContext
17.2.3 渲染缓存的创建
用于在屏幕上呈现的存储渲染图像的OpenGL对象。
renderbuffer 也称为颜色缓存,因为从本质上来说,使用其中存储的颜色来显示。
glGenRenderbuffers() 创建。
glBindRenderbuffer() 通知OpenGL,每当指向GL_RENDERBUFFER,就意味着传递给该对象。
renderbufferStorage:
1468
17.2.4 帧缓存的创建
framebuffer:是一个包含一个渲染缓存和其他一下缓存(如一个深度缓存、模板缓存和积累缓存)的OpenGL的对象。
创建过程和渲染缓存类似。
17.2.5 屏幕的清理
glClearColor、glClear、presentRenderbuffer
17.2.6 OpenGLView和app的委托关系
17.3 Core Animation
CoreAnimation把与视图对象相关联的层存储在一个树层结构中,层树中的每个层都有一个父类,但可以嵌入任意数量的子层,而不需要同时添加相应的视图,当实现某种特殊的视觉效果,而又不需要在视图上保持这种效果时,可以使用该技术。
CALayer对象。
Core Animation额外维护两组层对象,称之为树和渲染树。
17.3.1 层和变换
锚点 anchorPoint
17.3.2 树层结构
17.3.3 层上下文和层行为
1485
明天再看一遍CA,今天没看进去。
17.3.4 动画
显示动画,添加动画层并添加到层树中。
17.3.5 事务
每一个Layer的修改都会涉及一个事务transaction.
CATransaction,隐式事务和显式事务。
显示事务:在同一时间对许多层的属性进行设置。
17.3.6 动画层布局
17.4 案例实战
17.4.1 案例:设计过渡动画
CATransition过渡。控制UIView内子控件过渡动画。
startProgress 开始进度 endProgress 结束进度。
多种翻页效果。
17.4.2 案例:设计属性动画
CAPropertyAnimation控制:子类包括CABasicAnimation(只有开始和结束两个信息)、CAKeyframeAnimation(指定多个信息)等
所有支持数值型属性值的属性都可作为动画属性。
17.4.3 案例:设计路径动画
CAKeyframeAnimation通过path属性指定CALayer的移动路径。
控制小鱼转圈。
17.5 小结
UIView由一个特殊的CoreAnimationLayer支持,为CAEAGLLayer对象,是OpenGL ES 和 Core Animation联系的桥梁。
18 多媒体开发
18.1 使用声音
框架选择:
AVFoundation:OC接口。
Audio Toolbox:解析音频流、音频格式转换等。
Audio Unit:音频处理插件。
OpenAL:在游戏和其他app中回放位置音频。
MediaPlayer:播放iPod中的音频。
CoreAudio框架
18.1.1 音频编解码
大多数音频格式都支持基于软件的编解码。出于性能的考虑,要合适的使用硬解码,性能影响比软解码要小。
可以硬解码的音频格式。
不能通过硬解码同时播放多个音频。
PCM(无压缩) IMA4(有压缩)
18.1.2 音频回放和录制格式
iOS支持的音频回放格式。
iOS支持的音频录制格式。
iOS如何支持单路或多路音频格式。
多路:共用同一个硬件路径,要采用硬编码+软编码结合的方式。
1509
18.1.3 音频会话
Core Audio能够影响的行为。
范畴
中断和路由变化
硬件特征
18.1.4 播放音频
后台播放
18.1.5 通过iPod媒体库访问接口播放媒体项
18.1.6 使用系统声音服务播放声音及触发震动
18.1.7 通过AVAudioPlayer类轻松播放声音
18.1.8 用音频队列服务播放和控制声音
18.1.9 创建一个音频队列对象
18.1.10 控制回放音量
18.1.11 指示回放音量
18.1.12 同时播放多路声音
18.1.13 使用OpenAL播放和定位声音
控制游戏音频。
18.1.14 录制音频
AVAudioRecorder
18.1.15 解析音频流
网络音频流。
18.1.16 iOS系统上的音频单元支持
18.1.17 iPhone音频的最佳实践
afconvert命令行工具进行广泛的音频数据格式和文件类型转换。
18.2 使用视频
18.2.1 录制视频
UIImagePickerController对象。
18.2.2 播放视频文件
MediaPlayer框架
MPMoviewPlayerController类。
18.3 案例实战
18.3.1 案例:播放音效
18.3.2 播放音乐
AVAudioPlayer
18.3.3 案例:播放视频
18.3.4 案例:录制音频
18.3.5 案例:录制视频
18.4 小结
19 设备管理
19.1 硬件检测
19.2 配件通信
External Accessory框架,管道机制。
1563
19.2.1 配件基础
EASession类
NSInputStream和NSOutputStream对象。
19.2.2 声明协议
info.plist中声明支持的协议。
19.2.3 连接配件
19.2.4 监控配件
注册通知。
或遵守EAAccessory Delegate协议。
19.3 使用加速器
3个轴向。
UIAccelerometer对象接收数据。
数据更新的最小间隔为10毫秒,对应于100HZ的刷新率。
将代理设置为nil就会停止加速计事件。
静止时数据会有轻微的波动,可以通过取平均值进行调整。
19.3.1 选择更新频率
选择合适的更新频率,技能满足需求,又能提高电池寿命。
19.3.2 分离重力数据
低通滤波器算法:当前滤波前数据的10%和前一个滤波后数据的90%
19.3.3 分离实时运动数据
高通滤波器算法:当前加速计数据-低通滤波值
19.3.4 获取设备方向
大体而非精确:UIDevice类的相关方法。
打开加速计硬件,通过通知来获取方向或手动获取。
关闭加速计。
19.4 使用位置和方向
CoreLocation框架。
19.4.1 获取当前位置
控制在最小程度,比较耗电,会像基站、Wi-Fi或GPS查询。
对时间戳进行检验,因为位置服务通常会立即返回最后缓存的位置事件,得到一个大致的固定位置可能要花几秒钟的时间,更新之前的数据只是反映最后一次得到的数据。
位置请求返回的顺序有时可能和时间戳指示的顺序不同。
19.4.2 获取方向事件
两种方法:
- 包含GPS硬件的设备可以提供大致信息,
- 包含磁力计的设备可以提供更精确的方向信息,CLHeading类
磁力计可以测量地球散发的磁场,进而确定设备的准确方向。
Info.plist配置必须具有GPS和磁力计硬件。
19.5 使用地图
MapKit
19.5.1 添加地图视图
19.5.2 缩放和移动地图
1584
19.5.3 显示用户当前位置
19.5.4 坐标和像素切换
地图坐标和视图对象的本地坐标系统转换。
covertCoordinate:toPointToView:
19.5.5 显示注解
注解是定义并放置在地图上面的信息片段。
19.5.6 添加和移除注解对象
不应直接在地图上添加注解视图,而是应该添加注解对象。
19.5.7 定义注解视图
MKAnnotationView
MKPinAnnotationView
19.5.8 创建注解视图
复用。
19.5.9 处理注解视图中的事件
19.5.10 获取地标信息
获取与地图坐标相关联的地标信息,方便用户理解。
MKReverseGeocoder类。
反地理编码。
19.6 使用照相机
UIImagePickerController类。
使用前确认相机状态是否可用。
19.7 使用照片库
UIImagePickerControllerSourceTypePhotoLibrary
19.8 使用邮件
MFMailComposeViewController
19.9 案例实战
19.9.1 案例:管理通信设备
UIApplication openURL:
19.9.2 案例:获取加速度、陀螺仪、磁场数据
CMMotionManager
19.9.3 案例:获取移动数据
CMMotionManager返回的CMDeviceMotion对象
19.9.4 案例:获取位置信息
CoreLocation框架,蜂窝基站、Wi-Fi信号、GPS信息。
19.9.5 案例:地图定位
19.10 小结
20 文件和数据操作
20.1 文件操作
创建、删除、复制、剪切、粘贴。
一些原则。
20.1.1 iPhone常用目录
Documents
Preferences
Caches
Tmp
20.1.2 获取程序目录路径
如果使用带有ANSI C编程接口的框架,可以将一个NSString对象强制转换为一个CFStringRef类型。
NSSearchPathForDirectoriesInDomains()函数最初是为Mac OS X设计的,电脑可能存在多个这样的目录,所以返回一个路径数组,而不是单一路径,iOS中数组只包含一个特定路径。
1627
20.1.3 文件更新
更新app时文件不会被移除:
其他目录可能被保留,也可能被删除。
20.1.4 文件备份和恢复
iTunes自动备份,<<<< 除了 >>>以下几个目录:
/AppName.app
/Library/Caches
/tmp
数据量大或频繁变化的文件,应该放在Caches目录下,而不是Documents目录。
20.2 数据读写
20.2.1 文件数据的读写
20.2.1.1 Foundation框架
- plist文件转NSData
- NSCoding协议可以通过NSKeyedArchiver类
- NSFileHandle随机访问
- NSFileManager创建和操作
20.2.1.2 Core OS调用
fopen、fread、fwrite
mmap、munmap
20.2.2 属性列表数据的读写
plist文件
20.2.3 用归档器对数据进行读写
将任意的对象集合转换为字节流。
20.2.4 将数据写到Documents目录
20.2.5 从Documents目录对数据进行读取
文件较大时,应该避免一次性地装载整个文件,可以考虑使用mmap()函数或NSData的initWithContentsOfMappedFile:方法来将文件映射到内存。
20.2.6 保存状态信息
选择合适的时机保存数据。
20.3 SQLite
包含在一个相对较小的C库中,设计目标时嵌入式的。占用资源非常低。
20.3.1 数据类型
SQLite时动态类型
大部分关系型数据库列的类型在创建表的时候就确定了。
动态类型,会根据存入值自动判断,列的类型由值决定。
- NULL
- INTEGER
- REAL
- TEXT
- BLOB
20.3.2 常用函数及返回编码
数据库创建关闭类、
数据操纵语句类、
数据查询填充语句类
20.3.3 操作数据库
20.3.4 创建表
预处理和执行创建。