OC简介
语言简介
- 完全兼容C语言
- 通过LLVM(LowLevelVirtualMachine)编译器架构,支持与swift的双向互通
时空角
clang或gcc命令行 ```shell clang -fobjc-arc HelloWorld.m -o HelloWorld
gcc -v gcc main.c => a.out ./a.out
编译
cc -c mian.c => main.o
链接,增加启动代码
cc main.o => a.out
执行
./a.out
<a name="yka4X"></a>
### IDE
- Xcode
- 构建大型项目,追求质量和代码组织
<a name="29DC2"></a>
## 代码基础
- Mac上不能直接写NTFS格式的硬盘,需要TuxeraNTFS软件
- C语言开发步骤
1. 编码 touch main.c
2. 编译 cc -c main.c => main.o
3. 链接 cc main.o => a.out (源码增加启动代码)
4. 执行 ./a.out
- .h是头文件,.m是实现文件
- #import优于#include,解决了循环依赖的问题
<a name="REOpx"></a>
# 类与对象
<a name="PXTWt"></a>
## 类型系统
- 引用类型ReferenceType
- 类class
- 指针pointer
- 块block
- 值类型ValueType
- 基础类型
- 结构struct
- 枚举enum
<a name="Mg78X"></a>
## 类型装饰
- 协议 protocol
- 类别 categary
- 扩展 extension
<a name="0vrD4"></a>
## 类与结构
| | 类 | 结构 |
| --- | --- | --- |
| 类型与实例 | 类与对象 | 结构与值 |
| 类型 | 引用类型 | 值类型 |
| 面向对象 | 有属性、有方法(-表示实例方法 +表示类方法) | 只有属性、没有方法 |
| 内存结构 | 引用位于栈上的指针,指向堆上的对象 | 实例直接位于栈中 |
| 空间分析图 | 下图1 | 下图2 |
![对象的空间分析.png](https://cdn.nlark.com/yuque/0/2020/png/1491874/1602160314564-ae42fa5d-bc19-4941-b614-7e93be1cd58b.png#height=1134&id=c8bo6&originHeight=1134&originWidth=1780&originalType=binary&ratio=1&rotation=0&showTitle=false&size=463244&status=done&style=none&title=&width=1780)<br />![值的空间分析.png](https://cdn.nlark.com/yuque/0/2020/png/1491874/1602160321067-b8806e3b-eb0f-4c5c-9a5f-5da4144fd5b3.png#height=1136&id=ZUQ2K&originHeight=1136&originWidth=1526&originalType=binary&ratio=1&rotation=0&showTitle=false&size=295524&status=done&style=none&title=&width=1526)
<a name="Qqlfv"></a>
## 堆栈
<a name="8e34r"></a>
###
| 堆 | 栈 |
| --- | --- |
| 存储引用类型对象 | 存储值类型 |
| 创建对象时需要手动请求分配空间,释放由运行时ARC机制自动释放 | 无ARC负担,由系统自动管理,以函数为单位,函数执行时自动分配stack,执行完毕自动回收 |
| 具有全局性,空间大小受系统限制,超出会报OOM | 空间大小编译时确定(参数+局部变量)具有局部性,大小有限额,超出会报SOF |
| 函数之间通过拷贝引用传递 | 函数之间通过拷贝值传递 |
<a name="XHXYL"></a>
# 类型成员
<a name="PCS4w"></a>
## 数据成员
DataMember,描述对象状态
- 实例变量 instanceVariable
- 只在类内部访问
- 生存周期
- 实例变量的存储是跟随对象实例存储在堆上
- 值类型的实例变量内嵌在对象实例上,跟随对象实例的释放而被释放
- 引用类型的实例变量通过指针“引用”堆上的类型实例
- 属性 property
- 描述对外接口,默认编译器会为属性定义propertyName自动合成以下内容
- getter访问器 propertyName
- setter访问器 setPropertyName
- 实例变量 _propertyName
- 类外部使用一律使用属性访问
- 类内大多通过self使用属性访问,只有以下情况使用实例变量访问
- 初始化器 init
- 析构器 dealloc
- 自定义访问器方法
- 属性的描述特性attribute,指定属性不同环境下不同功能
- 读写特性
- readwrite 默认
- readonly
- 多线程特性
- atomic 默认
- nonatomic
- 内存管理特性
- ARC环境
- strong 默认
- weak 弱引用,阻止循环引用,防止内存泄漏
- copy 创建独立拷贝,防止引用连带
- 其他情况
- retain
- assign
- unsafe_unretained
<a name="ZHQ71"></a>
## 函数成员
FunctionMember,描述对象行为
- 方法 method
- 分类
- 全局函数(C语言函数)
- 成员函数(OC方法)
- 所有方法默认为公开方法,没有private或protected
- 动态消息分发:方法调用通过运行时动态消息分发实现,在对象上调用方法又称给对象发送消息
- 修饰符号
- -表示实例方法,可以访问
- 实例变量
- 实例属性
- 实例方法
- 类静态变量
- 类方法
- +表示类方法,可以访问
- 类静态变量
- 类方法
- 方法参数
- 如果参数为值类型,则为传值方式
- 如果参数为引用类型,则为传指针方式
- 方法可以没有参数,也可以没有返回值
- 如果方法有参数,方法名约定包含第一个参数名,从第二个参数开始需要显式提供外部参数名
- 调用时第一个参数名忽略,后面的参数名显式标明
- 动态方法调用机制——消息分发表,id类型的obj可以通过指针指向的methodlist找到真正的方法内存地址,即可以通过id类型调用方法
- 初始化器 init
- 对象初始化器
- -(id) init
- 可以重载多个
- 初始化对象实例时,init通常和alloc搭配使用
- alloc
- NSObject已实现,不用自定义
- 在堆上分配合适大小的内存
- 将属性或实例变量的内存置为0
- init
- 需要自定义
- 首先调用父类的初始化器[super init]
- 初始化当前对象的实例变量,这里不能使用属性
- new 调用相当于alloc和init的无参版本
```objectivec
-(id) initWithName:(NSString*) name WithPages(int) pages
{
self = [super init]
if(self){
_name = [name copy]
_pages = pages
}
return self;
}
- 类型初始化器
- +(void) initialize
- 只能有一个,负责类型的初始化
- 在每个类使用之前被系统自动调用,且每个进程周期只能被调用1次,无法手动调用
- 子类的initialize会自动调用父类的initialize
- 析构器 dealloc(用于释放对象拥有的资源,是一个没有返回值的函数)
- 对象析构器
- 一个类型在另外类型基础上进行的扩展实现,所有类的基类NSObject
- 每个类只能有一个基类,子类自动继承基类的
- 实例变量,使用->访问
- 属性
- 实例方法
- 类方法
- 继承的两层含义
- 成员复用,子类复用基类成员
- 类型抽象,将子类当作父类来使用【IS-A关系】
- init
- 子类自动继承父类的初始化器
- 子类可以重写父类的初始化器,此时必须手动调用父类的一个初始化器
- dealloc
- 子类可以选择继承父类的析构器,也可以重写
- 子类析构器执行完毕后会自动调用父类的析构器(后置调用且不支持手动调用)
-
多态
不同类型针对同一接口的不同实现方式
- 子类在父类统一行为接口下表现出不同的实现方式
- 重写和重载
- 重写:子类重写父类同名同参方法:子类只可以重写父类方法
- 重载:方法名相同,参数不同:OC不支持重载
- 子类的代码中,可以使用super来调用父类的实现
- self具有多态性,可以指向不同的子类
- super没有多态性,仅指向当前父类