1. 程式人生 > >黑馬程式設計師——IOS基礎——OC記憶體管理

黑馬程式設計師——IOS基礎——OC記憶體管理

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

基本型別資料存放在棧中,物件存放在堆中

棧中的資料系統自動回收

堆空間中的資料動態分配,不能自動分配,容易引起記憶體洩露

需要給物件傳送訊息,讓它回收,即呼叫物件的回收方法

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;
}

====================多個物件記憶體管理完====================