1、@property语法知识介绍
格式:@property(参数1,参数2) 类型 名字;
参数说明:参数可有可无,默认为atomic,表示给方法加锁,保证线程安全。
参数主要分为3类:
1)读写属性:readwrite/readonly :有getter和setter方法/只有getter方法
2)setter处理:assign/retain/copy:直接赋值/需要管理内存,计数器加1/拷贝(分深拷贝和浅拷贝)
3)原子性:atomicity/nonatomic :加锁,只能一个线程调用/不用考虑线程安全,可以多线程调用
例子:
(1)在声明文件中当属性为对象时,写法为:
@property (retain) Book *book;
(2)当属性为基本类型时,写法为:
@property (assign) int age; 默认的也是assign,所以也可以省略不写
特别说明:
声明文件中:
@property (retain) Book *book;
等价于实现文件中的以下代码:
-(void) setBook : (Book *) book{
if(_book ! = book){
[_book release];
_book = [book retain];
}
}
-(Book *) book;
(3)@property (nonatomic, getter = isRich) BOOL rich;
表示调用的getter方法名叫isRich;
2、autorelease pool 自动释放池介绍
(1)概念:自动释放池是OC里面的一中内存自动回收机制,一般可以将一些临时变量添加到自动释放池中,统一回收释放。
当自动释放池销毁时,池里面的所有对象都会调用一次release方法。
自动释放池可以建立多个。
(2)autorelease作用:OC对象只需要发送一条autorelease消息,它不会retain计算器也不会release一次计算器,只会把这个对象添加到最近的自动释放池中(栈顶的释放池),autorelease实际上只是把对release的调用延迟了,对于每一次autorelease,系统只是把该对象放入了当前的autorelease pool中,当该pool被释放时,该pool中的所有对象都调用release操作一次。
第一种例子如下:(使用动态方法创建一个对象)
main.m文件:
#import<Foundation/Foundation.h>
#import”Student.h”
int main(int argc,const char * argv[])
{
@autoreleasepool{
Student *stu =[[Student alloc]init];//创建一个stu对象
[stu autorelease];//把stu这个对象放入释放池中去,当池子销毁的时候,所有对象都会release一次
以上两句代码可以写成Student *stu =[[[Student alloc]init] autorelease];
}
return 0;
}
第二种例子如下:(使用静态方法创建一个变量,在静态方法销毁该变量)
在Student.m文件中
#import<Foundation/Foundation.h>
@implementation Student
+(id) student{
Student *stu = [[[Student alloc] init] autorelease];//在静态方法里创建一个对象,autorelease把该对象放入到调用该方法最近的一个释放池中去。
return stu;
}
@end
在main.m文件中调用该静态方法创建一个对象
#import<Foundation/Foundation.h>
#import”Student.h”
int main(int argc,const char * argv[])
{
@autoreleasepool{
Student *stu =[Student student];//调用静态方法创建一个stu对象
}
return 0;
}
例子总结:自动释放池的好处就是开发者不用再考虑在哪里放置[stu release];语句销毁对象了,一切交给自动释放池管理。
注意点:
1.在ARC下,不能使用[[NSAutoreleasePool alloc] init],而应使用@autoreleasepool
2.不要把大量循环操作放到同一个NSAutoreleasePool之间,这样会造成内存峰值的上升。
3.尽量避免对大内存使用该方法,因为这种机制是延迟释放。
4.sdk中一般利用静态方法创建并返回的对象都是已经autorelease的,不需要再进行release操作。