一、面向对象
- OO(Object Oriented) 面向对象
- OOP(Object Oriented Programmint) 面向对象编程
面向过程编程以事件为中心,程序围绕事件,列出了事件的每个步骤,一步一步完成;
面向对象编程以事物为中心,程序围绕事物展开,完成事件只是一个任务;
二、面向对象三大特性
- 封装:将现实世界中存在的某个客体的属性与行为绑定在一起,并放置在一外逻辑单元内;
- 继承:子类自动共享父类数据结构和方法的机制;
- 多态:相同的操作或者函数,过程可作用于多种类型的对象上并能获得不同的结果;
objective-c是一种能够完成复杂面向对象编程的简单的计算机语言,通过提供用于定义类和方法的语法,它扩展了标准的ANSI C程序设计语言。还提供类和接口(任何类都可采用)的动态扩展;
三、类对象的初始化
为了分配对象,需要发送alloc消息给该消息的类,来获取一个原始(未初始化)的实例,分配对象时,oc运行时会从应用程序的虚拟内存为对象分配足够的内存,除分配内存外,运行时在分配期间还会将所有实例变量设定为0。
分配原始实例后,必须要对它初始化,初始化的过程将一个对象的初始状态(即实例变量和属性)设定为合理的值并返回对象,初始化的目的在于返回可用的对象,原始初始化init会将内存中的所有对象清0;
1.自定义初始化方法:
创建对象分两步:分配空间和初始化,初始化的作用就是为对象赋初始值,初始化方法通常以init开头;
super
:将消息发送给父类对象;
self
:将消息发送给本对象(self始终代表接收消息的对象);
[super init]
就是将init消息发送给父类对象;
2.指定初始化方法:
通常情况下是指能够赋值最多的方法;
四、类的属性及成员变量
属性是一组设置器与访问器,与类相似,属性需要声明和实现;
属性的声明写在类的.h文件中:
@property int age;
上面的代码实际上相当于声明了两个方法
-(void)setAge:(int)age;
-(int)age;
属性的实现写在类的.m文件中:
@synthesize age = _age;
该语句的作用是使setAge
、以及age
方法都是在操作实例变量_age
,如果类对象没有_age
实例变量,编译器会自动声明一个实例变量_age
,并且属性名是age
;
相当于实现了两个方法:
-(void)setAge:(int)age { _age = age; }
-(int)age{ return _age; }
属性也可以设置特性:
1.读写特性:
readwrite|readonly
getter = 方法名 // 指定访问器的方法名
setter = 方法名 // 指定设置器的方法名
2.原子性特性:
nonatomic // 非原子性,不保证多线程安全
atomic // 原子性,多线程访问时较安全
3.setter/getter语义特性:
assign // 直接赋值(适用于基本数据类型int,float,struct)
retain // 赋值时做内存优化 (适用于对象类型)
copy // 复制一个副本 (适用于特殊的对象类型)
属性和实例变量是不同的,前者是一组方法,后者是一个变量,定义属性使用@property
和@synthesize
;
对于属性的特性定义:基本数据类型使用assign
,对象类型使用retain
,实现了NSCopying
协议的对象使用copy
。
五、内存管理
OC采用”引用计数机制”(retainCount)管理对象所占用的内存;
在OC语言中,NSObject类及子类的实例对象包含一个整形属性,用来统计当前的引用计数;
实例对象的生命周期:起始于alloc,终止于dealloc;
通过对类发送alloc消息,获得的实例对象的引用计数赋值为1,当实例对象的引用计数为0时,自动对该对象发送dealloc消息;
- copy 制造一个副本,将副本的引用计算赋值为1,并且拥有副本的所有权
- retain 对象引用计数+1,并拥有对象所有权
- release 对象引用计数-1,并放弃对象所有权
- autorelease 未来某个时间对象引用计数-1,并放弃对象所有权;
指针变量和对象区别联系:
对象是放在堆里面的,而指针变量是放在栈里面的,唯一的关系是指针变量存的是对象的地址;
非ARC下设置对象的实例属性
@property(retain, nonatomic) Student *stu;
1
-(void)setStu:(Student *)stu
{
[stu retain]; // 拥有对象所有权
[_stu release]; // release 之前的_stu,放弃所有权
_stu = stu;
}
dealloc方法在对象引用计数为0的时候自动被调用,主要用于释放自身所占有的资源,永远不要手动调用dealloc;
-(void)dealloc
{
[_stu release];
[super dealloc];
}
六、自动释放池
1.使用NSAutoreleasePool类
当创建的对象未来某个时候销毁时,可以用对象的autorelease方法;对象会将所有权交给最近的NSAutoreleasePool对对象,当池对象drain或者release时,会逐一对池内的对象发送release消,尽量不要使用autorelease,而是使用release;
2.早期版本的自动释放池
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
// TODO
Student *stu = ...;
[stu autorelease];
[pool release];
3.现版本的创建
@autorelesepool{
Student *stu = ...;
[stu autorelease]; // 将所有权控制交给pool,stu不用手动release;
}
4.便利构造器
+(id) studentWithName:(NSString *)name
{
Student *stu = ...;
return [stu autorelese];
}
内存管理原则:
- 1.凡是使用alloc、retain、copy的地方,就要有release或者autorelease与之对应,他们要配对使用;
- 2.属性为retain或者copy的话,需要在类的dealloc中释放这个属性;
- 3.便利构造器本身应该包含autorelease(系统框架中的便利构造器已经包含autorelease,所以使用便利构造器获取得的对象不需要release);
- 4.一定不要释放没有所有权的对象,不要手动调用dealloc;
在dealloc中输出NSLog,看dealloc是否执行来判断对象是否释放;
关于内存管理,在最新版本的OC中,已经不需要我们手动去release了。
内存检测工具:
Analyze 内存静态分析(编译期)
leaks(Instruments) 内存泄露检测工具(运行期)
网友评论