1、Objective-C類中實現了引用計數器,對象知道自己當前被引用的次數
2、最初對象的計數器爲1
3、如果需要引用對象,可以給對象發送一個retain消息,這樣對象的計數器就加1
4、當不需要引用對象了,可以給對象發送release消息,這樣對象計數器就減1
5、當計數器減到0,自動調用對象的dealloc函數,對象就會釋放內存
6、計數器爲0的對象不能再使用release和其他方法
-retain 不買狗只在狗的身上套繩子 前提是要有對象 引用計數+1 對應於release
-copy 按照原來狗的標準進行再買個狗 有了新的對象 開闢了新的空間相當於一個新的alloc 引用計數+1
-autorelease 將對象放到自動釋放池裏 當自動釋放池結束時會執行release操作 引用計數-1
[per retain];//計數1~2
[per retain];//計數2~3 內存沒釋放 內存泄露 此時棧區的對象沒有釋放
per = @"aa";//常量區將地址給per 地址發生變化 計數爲無窮大
[per release];//常量區內存系統自動釋放 不需要人工釋放
[per release];
}
NSLog(@"哈哈");
[super dealloc];
}
NSLog(@"%lu",[per retainCount]);//1
[per release];//1~0立即減一
//autorelease作用:將對象放入離它最近的釋放池中.
//當自動釋放池銷燬時,會向池中的每一個對象發送release消息.
[per autorelease];//1~0
/**3.
* 1
test
哈哈(重寫了dealloc方法)
*/
@autoreleasepool {
[per autorelease]; //1~0放到小池子裏
[per autorelease]; //過渡釋放
/**2.
* 1
哈哈(重寫了dealloc方法)
*/
}
NSLog(@"test");
[per autorelease]; //過渡釋放
/**3.
* 1
test
哈哈(重寫了dealloc方法)
*/
}
Person *per = [[Person alloc] init];
[per autorelease];
}
@autoreleasepool {
Person *per = [[Person alloc] init];
[per autorelease];
}
}
Person *per = [[Person alloc] init];
[per release];
}
8.重寫dealloc方法
- (void)dealloc{
NSLog(@"哈哈");
[super dealloc];
}
//if判斷是判斷原有對象是同一個,如果是同一個人就沒與必要重新賦值,否則就顯release,release之後空間系統被回收 此時如果retain就成爲野指針問題.
- (void)setTeach:(Teacher *)teach{
if (_teach != teach) {//如果是不同的空間
//setter是給實例變量賦值來用
[_teach release];//先將原來的保有的所有權釋放計數減1 解決內存泄露問題
//讓實例變量保有新的所有權 解決野指針問題
_teach = [teach retain];
//對於將來要做的一些對象,可以持有一份 將引用計數加1 解決野指針問題
// self.teach = teach;死循環了 不能調用自己
}
}
return _teach;
}
//當該類對象的引用計數爲零會自動調用該類的dealloc方法
//當調用dealloc方法時本類對象的空間將會被回收 在空間回收之前,將保有的其他對象的所有權給釋放掉.
[_teach release];//釋放retain的所有權 引用計數-1操作
[_teach1 release];//只要有retain就要釋放
NSLog(@"hahahha");
[super dealloc];//繼承父類的dealloc方法.
}
-(void)setTeach1:(Teacher1 *)teach1{
if (_teach1 != teach1) {
[_teach1 release];
//如果相對一個對象copy操作,對象的類必須符合一個NSCopying協議,並且實現協議中的方法
//解決方案:實現協議操作
_teach1 = [teach1 copy];
}
}
-(Teacher1 *)teach{
return _teach;
}
//姓名
NSString *_name;
//性別
NSString *_gender;
}
@property (nonatomic,retain) NSString *name;
@property (nonatomic,retain) NSString *gender;
- (id)initWithName:(NSString *)name gender:(NSString *)gender;
+ (id)teacherWithName:(NSString *)name gender:(NSString *)gender;
- (void)dealloc;
@end
//實現協議
- (id)copyWithZone:(NSZone *)zone{
Teacher1 *newTeacher = [[Teacher1 allocWithZone:zone]init];//開闢空間 alloc操作引用計數加1 對象發生變化
newTeacher.name = self.name;//賦值操作
newTeacher.gender = self.gender;
return newTeacher;//返回對象
}
- (id)initWithName:(NSString *)name gender:(NSString *)gender{
self = [super init];
if (self) {
// _name = name;可能會出現野指針問題 相當於賦值操作 引用計數不會加1
self.name = name;//內部調用setter方法添加了retain操作 保有了對象的所有權 引用計數+1
self.gender = gender;
}
return self;
}
+ (id)teacherWithName:(NSString *)name gender:(NSString *)gender{
return [[[Teacher1 alloc]initWithName:name gender:gender ] autorelease];
}
- (void)dealloc{
NSLog(@"%@空間被回收了",self.name);
[_gender release];
[_name release];
[super dealloc];
}
@end
Teacher1 *tea = [Teacher1 teacherWithName:@"Frank" gender:@"man"];0 ~ 1
NSLog(@"%lu",[tea retainCount]);
下面的是內存堆積的問題 因爲便利構造器內部用的是autorelease
for (int i = 0; i < 100000000; i++) {
NSString *str = [NSString stringWithFormat:@"aaaaa"];
}
return [[[Teacher1 alloc]initWithName:name gender:gender ] autorelease];
}