黑马程序员技术交流社区
标题: OC内存管理整理(三) [打印本页]
作者: silenCetestifY 时间: 2016-2-17 10:44
标题: OC内存管理整理(三)
假设这时候Student类里有很多对象做属性,那么代码是这样:
#import "Student.h"
#import "Book.h"
#import "Card.h"
@implementation Student
-(void)setBook:(Book *)book{
if (_book != book){
[_book release];
_book = [book retain];
}
}
-(void)setCard:(Card *)card{
if (_card != card){
[_card release];
_card = [card retain];
}
}
-(void)dealloc{
[_book release];
[_card release];
[super dealloc];
}
@end
这些内存管理的set方法太啰嗦了,所以可以不手写这些set方法,而在属性定义的时候这样:
@class Book;
@class Card;
@interface Student : NSObject
@property (retain) Book *book;
@property (retain) Card *card;
@end
这里的retain代表先release旧值,然后retain新值,就不用写内存安全的成员对象的set方法了。所以所有OC对象最好都这么写,但是如果不写,就会生成不管理内存的标准getset方法。
对于常量类型的成员变量,有这样的写法:
@property (assign) int age;
这个assign可以不写,默认就是这样,而且不能写retain,非OC对象不需要管理内存。
Property后面可以带多个参数,用逗号间隔,比如:
@property (nonatomic,retain) Card *card;
这里可以写的属性有三种:
getter的处理:readwrite(默认)/readonly(只生成get方法),
setter的处理:assign(默认,直接赋值)/retain(先释放后ratain)/copy(先释放后copy),
原子性:atomic(默认,给getset方法加锁,线程安全)/nonatomic(禁止多线程保护,性能更好)。通常iphone开发不考虑线程安全。
对于BOOL类型,需要保证get方法变成IsXxxx,需要加上参数:
@property (nonatomic, getter = isRich) BOOL rich;
OC有自动释放池机制,这与java垃圾回收不同,在池子释放时,会对池子里所有的对象调用一次release方法(并不是销毁)。OC对象只要发送一条autorelease消息,OC就会把这个对象添加到释放池当中。所以说autorelease实际是把对象的释放延迟到池子释放了,但是它并不会改变计数器。
最常用的写法是:
@autoreleasepool {
Student *stu = [[[Student alloc]init]autorelease];
}
在OC中有一个潜规则,用来快速创建一个对象的静态方法和类名相同,而且静态方法都自动释放,比如有一个创建Student的静态方法:
@interface Student : NSObject
+(id)student;
@end
实现的时候一定要注意自动释放:
+(id)student {
return [[[Student alloc]init]autorelease];
}
静态方法一般都不需要我们手动来管理内存。
注意点:
在ARC下,只能使用@符号创建一个释放池。
不要把大量循环操作放在释放池下,因为这会导致大量循环内的对象没有被回收,这种情况下应该手动写release代码。
尽量避免对大内存对象使用autorelease,否则会延迟大内存的回收。
ios中很多对象都已经自动释放了,不需要手动再release。
Category(分类)可以动态地给已经存在的类添加方法,类似C#的扩展方法。需要新建一个文件,类型是OCcategory,在Category on当中选择目标类,会生成“类名+分类名”.h和.m两个文件,生成的类名右边括号里就是分类名。需要注意的是这个类的.h文件里必须import原始类,不能@class,原因是要知道原先类里有什么方法。
#import "Student.h"
@interface Student (Test)
-(void)test2;
@end
#import "Student+Test.h"
@implementation Student (Test)
-(void)test2{
NSLog(@"调用了test2方法");
}
@end
#import <Foundation/Foundation.h>
#import "Student.h"
#import "Student+Test.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
Student *stu = [Student student];
[stu test2];
}
return 0;
}
作者: silenCetestifY 时间: 2016-2-17 10:45
沙发!!!
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |