OC-內存管理

垃圾回收機制(gc):由系統管理內存,開發人員不需要管理內存
iOS從2.0版本加入垃圾回收機制
在ios平臺中不支持垃圾回收機制

ios沒有垃圾回收機制,那麼怎麼管理內存呢?
答:ios通過引用計數來管理內存

ios通過引用計數管理內存的兩種方式
答:1.MRC(手動引用計數), 由開發人員使用引用計數,管理內存.
2.ARC(自動引用計數),由系統自動管理引用計數

內存管理機制的原則:
1.自己創建對象,自己持有
2.非自己創建的對象,自己也能持有
3.不再需要自己持有對象時,釋放對象
4.非自己持有的對象無非釋放

注:開發人員能夠管理的內存,只有堆區的內存
MRC和ARC的混編
1.工程環境是ARC,部分文件想要使用MRC,加-fno-objc-arc
2.工程環境是MRC,部分文件想要使用ARC,加-fobjc-arc

創建並持有對象
alloc:引用計數從0到1
retainCount:引用計數,參考值
非自己創建的對象,自己也能持有
retain:引用加一
不需要自己持有對象時,釋放對象
release:-1

alloc:開闢內存
 dealloc:釋放內存 
retain:引用計數+1
 release:引用計數-1 
autorelease:引用計數-1

alloc,retain和 release, autorelease的次數相等

release和autorelease的區別:release是引用計數立即-1, autorelease是引用計數在未來的某個時刻-1
NSAutoreleasePool,自動釋放池,用於管理autorelease對象
使用方法,可以把autorelease的對象,放到自動釋放池中,自動釋放池傾倒池子時,會將內部存放的對象一一釋放
NSArray *array = [NSArray array];
如果對一個對象進行操作,需要先持有它
[array release];
這樣是錯誤的,array調用便利構造器,便利構造器是一個封裝的方法,array的引用計數爲0
若[array release]; 則首先需要持有它,即進行一個[array retain];
修飾符爲assign則自動生成的getter方法如下:
@property (nonatomic, assign) NSInteger age;
生成的getter和setter方法如下:

- (void)setAge:(NSInteger)age {
        if (_age != age) {
         _age = age;
    }
}

- (NSInteger)age {
return _age;
}

若修飾符爲retain
@property (nonatomic, retain) NSString name;
則生成的getter和setter方法如下:
- (void)setName:(NSString *)name {
if(_name ! = name) {
[_name release];
_name = [name retain];
}
}

- (NSString *)name {
//return[ [_name retain] autorelease];
return _name;
}
nil調用任何方法都不會崩潰


copy:複製對象
能夠使用copy的對象,必須遵循<NSCoping>
例如定義一個燈的類若想要Light這個類可以使用copy必須這個對象需要遵守NSCopying協議
如下:
在.h文件中
@interface Light : NSObject<NSCopying>//遵守NSCopying協議
然後再.m文件中實現<NSCopying>協議中的copyWithZone:(NSZone *)zone這個方法
- (id)copyWithZone:(NSZone *)zone {
Light *light = [[Light allocWithZone:zone]init];
light.name = _name;
return light;
}
在main函數中使用如下:
Light *light5 = [[Light alloc]init];
Light *light6 = [light5 copy];
如果使用copy這個修飾符
則自動生成的setter和getter方法如下:
- (void)setAddress:(NSString *)address {
if(_address != address){
       [_address release];
        _address = [address copy];
 }
}
- (NSString *)address {
  return _address;
}

用retain和copy修飾符的屬性,要在.m中重寫dealloc方法
初始化的時候,先初始化父類,在初始化自己, 內存回收的時候,先釋放子類,在釋放父類
- (void)dealloc {
[_name release];
[_address release];
[super dealloc];
}
便利構造器在內存中的實現
1.使用便利構造器創建對象,不能用release
2.便利構造器內部實現,return時,需要加autorelease
Person *person1 = [Person personWithName:@"ABC" age:123];
[person1 release];//這樣是錯誤的,系統會崩潰,是因爲person1的引用計數仍然是0,所以這樣的話,release,系統就直接崩潰了
在便利構造器中是如下實現的
+ (Person *)personWithName:(NSString *)aName age:(NSInteger)aAge {
Person *person = [[Person alloc]initWithName:aName age:aAge];
return [person autorelease];//分配了就要釋放,但是release是立即釋放,這個時候用autorelease,這樣在未來的某個時刻釋放.

}
集合在內存中的實現
存入集合的對象,集合會對其保留一次;當集合釋放的時候,會對存放到集合中的對象進行釋放
 //創建3Person對象,把它放到數組中
        Person *p2 = [[Person alloc] initWithName:@"1" age:11];
        Person *p3 = [[Person alloc] initWithName:@"2" age:22];
        Person *p4 = [[Person alloc] initWithName:@"3" age:33];
       
       
        NSMutableArray *mArray1 = [[NSMutableArray alloc]initWithCapacity:0];
        [mArray1 addObject:p2];
        NSLog(@" p2.retainCount:%lu", p2.retainCount);
        [mArray1 addObject:p3];
        [mArray1 addObject:p4];

        [p2 release];
        [p3 release];
        [p4 release];
        NSLog(@" p2.retainCount:%lu", p2.retainCount);
        
        [mArray1 release];

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