1.OC內存管理函數
1)範圍:管理任何繼承NSObject的對象,對其餘的基本數據類型無效(堆區),不然會形成內存泄露atom
2)原理:任何對象均可能有用一個或多個全部者,只要一個對象至少還擁有一個全部者,它就會繼續存在spa
3)對象的引用計數器,retain(+1)、release(-1)、retainCount獲得引用計數器的值3d
4)內存管理的分類:MRC(手動管理)、ARC(自動管理)、垃圾回收(不支持)指針
2.引用計數器的使用code
dealloc:釋放對象對象
先調用[super dealloc]blog
咱們建立一個項目,默認是ARC模式,先修改繼承
//
// main.m // 內存管理 //
// Created by fanyafang on 15/11/6. // Copyright © 2015年 itcast. All rights reserved. //
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) { @autoreleasepool { Person *p =[[Person alloc]init]; NSUInteger count=[p retainCount]; NSLog(@"%lu",count); //Person *p2=p;//不變 //Person *p2=[p retain];//加1
[p retain];//加1
[p release];//減一
[p release];//減一自動調用dealloc方法 //證實p的空間被釋放,能夠在Person類中重寫dealloc方法
} return 0; }
3.內存管理的原則ip
1)只要有人使用這個對象,這個對象就不會被回收
2)只要你想使用這個對象,那麼就應該讓這個對象的引用計數器加1
3)當你不想使用這個對象時,應該讓對象的引用計數器減1
4)誰建立(new、malloc、copy)誰release
5)誰retain誰release
4.若是一個對象已經被釋放了,這個對象就成爲殭屍對象,再去使用這個對象就沒有意義,默認不報錯,須要開啓殭屍對象檢測
不能使用retain讓殭屍對象起死回生
5.對象nil 類Nil NULL NSNull是一個對象
避免使用殭屍對象的方法是,對象釋放之後,給對象賦值爲nil
6.多個對象的內存管理
在set函數中先release實例對象,再retain傳入的對象
//若是是同一個對象的話就不須要release和retain
if(_car!=car){
[_car release];
_car=[car retain];
}
在dealloc中,release實例對象
[_car release];
7.@property參數
1.原子性atomic nonatomic
2.讀寫readwrite readonly
3.內存管理assign retain copy
替換get方法名稱setter=isVip,get方法名稱getter=isVip
8.@class的使用
使用import引入頭文件時,若是頭文件的內容發生了變化,此時全部引用這個頭文件的類都須要從新編譯
使用@class 類名;代替import
告訴編譯器xxx是一個類,不須要從新編譯
可是使用時會有提示錯誤,解決辦法,在.m文件中再import一次
@class的能夠解決循環引入問題,A類和B類互相import,使用class不會報錯
9.循環retain會致使兩個對象都會內存泄露
防止方法:1)讓某個對象多釋放一次(注意順序)
2)推薦方法:一端使用assign,另外一端使用retain
10.NSString對象
11.@autoRelease
若是一個方法須要放回一個新建的對象,該對象什麼時候釋放?
方法內部不會釋放,由於這樣作會將對象當即釋放而返回一個空對象,調用者也不會主動釋放該對象
這個時候就發生了內存泄露
1)@autoreleasepool {}建立自動釋放池
2)[對象 autorelease];//加入自動釋放池,發送消息,釋放池結束的時候調用對象的release
autorelease的嵌套:
1)自動釋放池的棧結構和內存的棧是不同的
2)對象存在棧頂的自動釋放池中
12.id和instancetype的區別
instancetype能夠智能幫咱們判斷賦值的指針變量的類型和方法的返回值類型是否一致
13.autorelease的使用場景
如父類是Person在父類的person方法中使用autorelease,Student繼承Person類
//
// Person.m // OC03 //
// Created by fanyafang on 15/11/7. // Copyright © 2015年 itcast. All rights reserved. //
#import "Person.h"
@implementation Person +(instancetype)person{ return [[[self alloc]init]autorelease]; } -(void)dealloc{ NSLog(@"Person釋放了!"); } @end
在main方法中,建立自動釋放池
#import <Foundation/Foundation.h>
#import "Student.h"
int main(int argc, const char * argv[]) { @autoreleasepool { //Person *p=[Person person];
Student *student = [Student person]; } return 0; }
14.重寫初始化方法
//
// Student.h // OC03 //
// Created by fanyafang on 15/11/7. // Copyright © 2015年 itcast. All rights reserved. //
#import <Foundation/Foundation.h>
@interface Student : NSObject @property(nonatomic,assign) int age; -(instancetype)initWithAge:(int)age; +(instancetype)StudentWithAge:(int)age; @end
//
// Student.m // OC03 //
// Created by fanyafang on 15/11/7. // Copyright © 2015年 itcast. All rights reserved. //
#import "Student.h"
@implementation Student -(void)dealloc{ NSLog(@"釋放了"); } -(instancetype)initWithAge:(int)age{ if(self=[super init]){ _age=age; } return self; } +(instancetype)StudentWithAge:(int)age{ return [[[self alloc]initWithAge:age]autorelease]; } @end
//
// main.m // 重寫初始化方法 //
// Created by fanyafang on 15/11/7. // Copyright © 2015年 itcast. All rights reserved. //
#import <Foundation/Foundation.h>
#import "Student.h"
int main(int argc, const char * argv[]) { @autoreleasepool { /* Student *stu=[[Student alloc]initWithAge:10]; NSLog(@"stu age%d",[stu age]); [stu release]; */ Student *stu=[Student StudentWithAge:20]; NSLog(@"stu age%d",[stu age]); } return 0; }