黑馬程序員----Objective-C學習筆記之@class與循環retain問題

------Java培訓、Android培訓、iOS培訓、.Net培訓--------

一、@class的使用方法

1、使用

@import】會把引用的頭文件整個拷貝到@import的使用處

如果該頭文件改變了,那麼所有引用它的文件都需要重新編譯,導致效率非常低

 

@class的使用】

格式:@class XXX;

【含義】告訴編譯器,XXX是一個類,至於類有哪些方法和屬性,此處不去檢測。

【好處】如果XXX文件內容發生了改變,而不需要重新編譯

【缺點】因爲無法檢測到引入類的方法和屬性,因此也無法訪問。

【解決方法】因爲編譯時先編譯.h頭文件,因此在.h頭文件中使用@class告知有要引入的類,.m文件是在運行時編譯,因此可以在.m文件中使用#import指定的頭文件,這樣只有程序運行的時候纔去檢查,然後重新編譯,可以極大地提高效率。

【注意】

1.h @class 類名;

2.m #import 類名;

 

2@class可以解決循環引入問題

例如:

有A、B兩個類,如果在A類頭文件中使用#import引入了B,又在B類頭文件中使用#import引入了A,這樣在就會報錯。

【解決方案】在兩個類的頭文件中使用@class引入對方的類名


二、循環retain問題

1、循環retain的問題

會導致兩個對象的內存泄露

【解決方案】

1)讓某個對象多釋放一次,(注意順序)

2)【推薦方法】一端使用assign一端使用retain

 

例子:

【人有一條狗,狗有一個主人】

【Person.h文件】

#import <Foundation/Foundation.h>
@class Dog;
 
@interface Person : NSObject{
    //人擁有一條狗,使用的是retain
    Dog *_dog;
}
@property(nonatomic,retain) Dog *dog;
@end


【Person.m文件】

#import "Person.h"
#import "Dog.h"
@implementation Person
-(void)dealloc{
   
    //人死前先把狗放了
    [_dog release];
    NSLog(@"This person dead....");
    [super dealloc];
}
@end


【Dog.h文件】

#import <Foundation/Foundation.h>
@class Person;
@interface Dog : NSObject{
    //狗有一個主人,使用retain
    Person *_p;
}
@property(nonatomic,retain) Person *p;
@end


Dog.m文件】

#import "Dog.h"
#import "Person.h"
@implementation Dog
-(void)dealloc{
    //狗跑之前先把主人咬死
    [_p release];
    NSLog(@"The dog is gone....");
    [super dealloc];
}
@end


main.m文件】

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Dog.h"
 
int main(int argc, const char * argv[])
{
 
    @autoreleasepool {
        //實例化一個person對象
        Person *p = [Person new]; //p的計數器值 1
        Dog *dog = [Dog new];//dog的計數器值 1
       
        p.dog = dog;//dog的計數器值 2
       
        dog.p = p;//p的計數器值 2
       
        [dog release];//dog的計數器值 1
        [p release];//p的計數器值 1
   }
 
    return 0;
}

結果分析】

最後dog和p的計數器值都爲1.最後兩個對象的堆區內存都沒有被釋放,導致了內存泄露。

【誤區】

一開始我認爲在delloc方法中,兩個對象不都把擁有的對象給release掉了麼?怎麼也想不明白爲什麼最後計數器值都爲1。最後終於明白了,只要記住一點【delloc只有在一個對象的計數器值爲0的時候由系統自動調用的】就行了。這樣是不是就明白了呢?

 

【解決方法1】任何一個對象多釋放一次,不過這樣需要注意順序,具體需要計算他們的計數器值

        [dog release];//dog的計數器值 1
        [p release];//p的計數器值 1
<span style="white-space:pre">	</span> [p release];//p的計數器值 1


【解決方法2:牆裂推薦】一端使用assign一端使用retain

只要把

Dog.h文件中的屬性改爲

@property(nonatomic,assign) Person *p;

Dog.m文件中的方法改爲

-(void)dealloc{
    NSLog(@"The dog is gone....");
    [super dealloc];
}


此時打印結果:

2015-10-06 15:31:53.418 MRCDemo[1967:303] The god isgone....

2015-10-06 15:31:53.420 MRCDemo[1967:303] This persondead....


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章