在Xcode4.2及之后的版本中已经引入了引入了ARC(Automatic Reference Counting)机制,程序编译时Xcode可以自动给你的代码添加内存释放代码。如果不使用arc机制就需要自己来进行内存管理了。
objective-c的内存管理机制使用的是引用计数器的原理。
当一个对象在创建之后它的引用计数器为1,当调用这个对象的alloc、retain、new、copy方法之后引用计数器自动在原来的基础上加1,当调用这个对象的release方法之后它的引用计数器减1,如果一个对象的引用计数器为0,则系统会自动调用这个对象的dealloc方法来销毁这个对象。
#import <Foundation/Foundation.h>
#import "HPPStudent.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
HPPStudent *stu1 = [[HPPStudent alloc] init];// 调用alloc方法,引入计数+1
NSLog(@"引用计数为:%d",[stu1 retainCount]);// retainCount为1
HPPStudent *stu2 = [stu1 retain];
NSLog(@"引用计数为:%d",[stu1 retainCount]);// retainCount为2
[stu1 release];
NSLog(@"引用计数为:%d",[stu2 retainCount]);// retainCount为1
[stu2 release];
}
return 0;
}
另外,怎么知道对象是否被释放呢?
对象释放的时候通常会调用dealloc方法
#import <Foundation/Foundation.h>
@interface HPPStudent : NSObject {
NSString *name;
}
- (void) setName:(NSString *)_name;
- (NSString *)name;
@end
#import "HPPStudent.h"
@implementation HPPStudent
- (void)dealloc
{
NSLog(@"%@ dealloc", name);
[super dealloc];//注意最后一定要调用父类的dealloc方法(两个目的:一是父类可能有其他引用对象需要释放;二是:当前对象真正的释放操作是在super的dealloc中完成的)
}
- (void) setName:(NSString *)_name {
if (_name != name) {//首先判断要赋值的变量和当前成员变量是不是同一个变量
[name release];//释放之前的对象
name = [_name retain];//赋值时重新retain
}
}
- (NSString *)name {
return name;
}
@end
属性参数@property和@synthesize
在上面的类的实现了,我们实现了getter和setter方法,实现了这个两个方法之后,我们就直接通过点运算符来访问对象并且进行对象的操作。
#import <Foundation/Foundation.h>
#import "HPPStudent.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
HPPStudent *stu1 = [[HPPStudent alloc] init];
stu1.name = @"mirhunana"; //使用点运算符
}
return 0;
}
其实,使用@property就可以自动添加getter、setter的声明,这样我们就不需要自行实现了。
#import <Foundation/Foundation.h>
@interface HPPStudent : NSObject
//当编译器遇到@property时,会自动展开成getter和setter的声明
@property (nonatomic,retain)NSString *name;
@end
@synthesize可以自动添加getter、setter的实现
#import "HPPStudent.h"
@implementation HPPStudent
@synthesize name;
- (void)dealloc
{
NSLog(@"%@ dealloc", name);
[super dealloc];//注意最后一定要调用父类的dealloc方法(两个目的:一是父类可能有其他引用对象需要释放;二是:当前对象真正的释放操作是在super的dealloc中完成的)
}
@end
这里使用@property和@synthesize的效果跟上面直接实现getter和setter的效果是相同的。
另外,我们可以看到,在声明中对属性也加了关键词进行修饰。
@property (nonatomic,retain)NSString *name;
对于属性或者变量的定义,我们可以使用关键词进行修饰。
有下面基类关键字:
@property的参数默认参数:(atomic,readwrite,assign)
assign,用于基本数据类型
-(void)setA:(int)a{
_a=a;
}
retain,通常用于非字符串对象
-(void)setA:(Car *)a{
if(_a!=a){
[_a release];
_a=[a retain];
}
}
copy,通常用于字符串对象、block、NSArray、NSDictionary
-(void)setA:(NSString *)a{
if(_a!=a){
[_a release];
_a=[a copy];
}
}
自动释放池
自动释放池就是将自动内存释放使用@autoreleasepool关键字声明一个代码块,如果一个对象在初始化时调用了autorelase方法,那么当代码块执行完之后,在块中调用过autorelease方法的对象都会自动调用一次release方法。
#import <Foundation/Foundation.h>
#import "HPPStudent.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
HPPStudent *person= [[[HPPStudent alloc] init] autorelease];//调用了autorelease方法,在autoreleasepool块结束位置会自动该对象进行释放操作
person.name = @"mirhuanan";
}
return 0;
}