iOS記憶體管理的方式是引用計數機制。分為MRC(人式引用計數)和ARC(自動引用計數)、 為什麼要學習記憶體管理? 記憶體管理方式是引用計數機制,通過控制對象的引用計數來實現操作對象的功能。一個對象的生命周期有生成,持有,釋放,銷毀。引用計數分為ARC,MRC,在MRC中,增加引用計數的方法是retai
iOS記憶體管理的方式是引用計數機制。分為MRC(人式引用計數)和ARC(自動引用計數)、
為什麼要學習記憶體管理?
記憶體管理方式是引用計數機制,通過控制對象的引用計數來實現操作對象的功能。一個對象的生命周期有生成,持有,釋放,銷毀。引用計數分為ARC,MRC,在MRC中,增加引用計數的方法是retain,alloc,new,copy。減少引用計數的方法是release, autorelease,當引用計數增減平衡的時候,系統會自動執行對象的dealloc方法,銷毀對象,完成該對象的記憶體管理。有創建就必須有釋放。
1.養成良好的記憶體管理習慣,可以從源頭上避免記憶體問題的出現。
2.一旦出現記憶體問題,能夠找到並用解決。(調試bug)
引用計數管理記憶體的理念是:通過控制記憶體或者對象的引用計數來實現生成,持有,釋放,銷毀對象的操作。
1.生成,對象的引用計數從0到1 - > 比如alloc
2.持有,增加一個引用,讓對象的引用計數加1 - >比如 retain
3.釋放,減少一個引用,讓對象的引用計數減1 - > 比如 release autorelease
4.銷毀,當對象的引用計數為0時,系統就會回收這個記憶體空間。 - > 比如 dealloc
當這塊空間被系統回收之後 ,就不能通過指針去訪問這塊空間了,容易造成野指針。
切記!!引用計數這個概念,只存在於堆區區域,針對堆區的對象。
生成,對應的方法是 + (instancetype)alloc; 在堆區域開闢一塊記憶體空間,存放對象,並且將記憶體清零,同時將此對象的引用計數變為1,是從0到1的過程。
//0 -> 1
Person *person = [[Person alloc] init];
//retainCount 這個方法可以查看對象的引用計數
NSLog(@"person is %p, person's retainCount is %lu",person, [person retainCount]);
//1
Person *p1 = person;
NSLog(@"p1 is %p, p1's retainCount is %lu", p1, [p1 retainCount]);
//持有, 方法是 retain,讓對象的方法加1
//1 -> 2
[person retain];
NSLog(@"person is %p, person's retainCount is %lu",person, [person retainCount]);
//2 -> 3
[p1 retain];
NSLog(@"p1 is %p, p1's retainCount is %lu", p1, [p1 retainCount]);
//3 -> 4
Person *p2 = [p1 retain];
NSLog(@"p2 is %p, p2's retainCount is %lu", p2, [p2 retainCount]);
//釋放 release,讓對象的引用計數減1 ,而且是立即減1
[person release];
NSLog(@"%lu",[person retainCount]);
[person release];
[person release];
NSLog(@"%lu",[person retainCount]);
[person release];//在執行這條release消息之前,對象person的引用計數為1,release之後,引用計數為0,此時系統會自動試行dealloc方法,釋放person對象,來完成person對象的記憶體管理。
//下麵這行代碼可以列印出retainCount,為1,因為系統內部引用計數的值沒有0,0只是方便交流引入的一個數,但從本質上來說, 這行代碼已經有可能造成了野指針,因為person對象已經被系統回收,再去訪問[person retainCount]就會出現問題。
//野指針崩潰,是因為被回收的記憶體空間已經被占用了,再去訪問會出現問題,不崩潰,只是僥幸,這塊被回收的記憶體空間現在還沒有被占用。
autorelease 此方法也是讓對象的引用計數減1,不過區別於release,TA並不是立即減1,而是在未來的某個時刻,觸發減1操作的這個時刻與自動釋放池息息相關。
自動釋放池是一個容器,來記錄池子內部對象接收到的autorelease消息,哪個對象接收,接收了幾次,誰先接收,誰後接收,當池子釋放時,autorelease消息真正執行減1操作。
- (void)dealloc{
NSLog(@"我的天,%@已經被釋放了",self);
[super dealloc];
}只要重寫了dealloc,[super dealloc]永遠都在最後一行。先將自身的實例變數釋放掉,然後再去執行父類中的dealloc方法,釋放,繼承過來的實例變數。dealloc方法釋放的順序,正好與初始化方法,初始化順序相反。