假设这时候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; }
|