黑馬程序員——IOS基礎——OC內存管理

------- android培訓java培訓、期待與您交流!

=====================引用計數器開始====================

基本類型數據存放在棧中,對象存放在堆中

棧中的數據系統自動回收

堆空間中的數據動態分配,不能自動分配,容易引起內存泄露

需要給對象發送消息,讓它回收,即調用對象的回收方法

1.系統如何判斷對象是否需要回收

需要理解對象內部結構:

每一個OC對象內部都有一個   引用計數器  (即被引用的次數),4個字節存儲空間

當減爲0時,回收

剛創建時,爲1

2.引用計數器的作用

當使用allocnew或者[mutable]copy創建一個新對象時,默認計數器爲1

如果對象計數器不爲0,他就不會被回收,一直在內存中

3.引用計數器的操作

>給對象發送一條retain消息,可以使對象計數器+1(retain方法返回對象本身)

>給對象發送一條release消息,可以使對象計數器-1

>retainCount返回引用計數器的值

4.引用計數器的銷燬

>當一個對象的引用計數器爲0時,他會被銷燬,所佔用的內存會被回收

>當一個對象被銷燬時,系統會自動向對象發送一條dealloc消息

>一般會重寫dealloc方法,並且一定要調用[super dealloc],並且放在最後在這裏釋放相關資源


重寫dealloc方法來看程序是否被回收:

- (void)dealloc{
	NSLog(@"對象被回收");

	//super的dealloc一定要調用,而且要放到最後面
	[super dealloc];
}


//調用:

原則:一調用alloc,就得調用一次release;一調用retain,就得調用一次release

int main(){
	Person *p = [[Person alloc] init];
	NSUInteger c = [p retainCount];//結果是1
	//[p release];//計數器-1,爲0,在main函數還沒有結束就已經回收了對象內存
	[p retain];//返回對象本身,計數器+2
	return 0;
}


殭屍對象已經被回收內存的對象

野指針指向殭屍對象(不可用內存)的指針

1.此時會報錯:EXC_BAD_ACCESS------由於訪問了一塊壞的內存(已經被回收,不可被訪問的內存)

2.如果繼續使用對象調用任何方法(包括[p retain]),則會報錯:-[Person setAge:]: message sent to deallocated instance 0x100109a10----會出現閃退

如何避免:設置p=nil    變爲空指針,p指針就不存在,給空指針發送消息就不會報錯(即p調用方法)

OC中不會報空指針錯誤

int main(){
	Person *p = [[Person alloc] init]; //1
	[p retain]; //2
	[p release]; //1
	[p release]; //0 被回收,此時Person對象成爲殭屍對象,指針p稱爲野指針
	[p release];//會報錯,
	return 0 ;
}


=====================引用計數器完====================

====================多個對象內存管理開始====================

當你想使用某個對象,應該對這個對象的計數器+1,不使用的時候-1

>誰創建  誰release

>誰retain 誰release


舉個栗子:

Book.h中:

#import <Foundation/Foundation.h>
@interface Book : NSObject
//@property int price;//價格  由於涉及內存,不用property,因爲它會屏蔽內存管理細節
{
	int _price;
}
- (void)setPrice:(int)price;
- (int)price;
@end 


Book.m中:

#import "Book.h"
@implementation Book
- (void)setPrice:(int)price
{
	_price = price;
}
- (int)price
{
	return _price;
}
//需要重寫dealloc方法
- (void)dealloc
{
	NSLog(@"Book對象被回收");
	[super dealloc];
}

@end


Person.h中:

#import <Foundation/Foundation.h>
#import "Book.h"
@interface Person : NSObject
{
	Book *_book;
}
- (void)setBook:(Book *)book;
- (Book *)book;
@end


Person.m中:

#import "Person.h"
@implementation Person
- (void)setBook:(Book *)book
{
	_book=[book retain];
}
- (Book *)book;
{
	return _book;
}
//需要重寫dealloc方法
- (void)dealloc
{
	[_book release];//人掛了,當然書就不用了
	NSLog(@"Person對象被回收");
	[super dealloc];
}
@end


主函數:

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Book.h"
int main(){
	Book *b = [[Book alloc] init];//書兩種情況需要被release:1.換一本書 2.人掛了    所以在這兩種情況都要加release
	Person *p1 = [[Person alloc] init];
	//p1想佔用b一次
	[p1 setBook:b];//去Person.m中讓book retain一次

	[b release];//b不想用Book對象了,就應該讓指針變空
	b=nil;

	[p1 release];//p1不用了,就用p1把對象人中的計數器-1,這時候計數器爲0,對象人就掛了,那人
	p1=nil;
	return 0;
}

====================多個對象內存管理完====================


------- android培訓java培訓、期待與您交流!

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