IOS記憶體管理知識總結(一)
最近優化公司在優化app,總結幾個記憶體管理的知識點。
首先我們要清楚
1. “堆”和“棧”
Objective-C的物件在記憶體中是以堆的方式分配空間的,並且堆記憶體是由你釋放的,就是release
OC物件存放於堆裡面(堆記憶體要程式設計師手動回收)
非OC物件一般放在棧裡面(棧記憶體會被系統自動回收)堆裡面的記憶體是動態分配的,所以也就需要程式設計師手動的去新增記憶體、回收記憶體
- 對於棧來講,是由系統編譯器自動管理,不需要程式設計師手動管理
- 對於堆來講,釋放工作由程式設計師手動管理,不及時回收容易產生記憶體洩露
- 堆是動態分配和回收記憶體的,沒有靜態分配的堆
- 棧有兩種分配方式:靜態分配和動態分配
- 靜態分配是系統編譯器完成的,比如區域性變數的分配
- 動態分配是有alloc函式進行分配的,但是棧的動態分配和堆是不同的,它的動態分配也由系統編譯器進行釋放,不需要程式設計師手動管理
2. 單例模式
單例模式是限制一個類只能初始化一個物件的一種設計模式,在實踐中,初始化通常在程式啟動不久後執行,而且這些物件不會銷燬,原理想必大家都很清楚,單例物件被一個全域性的靜態變數所引用,保證了他不會被釋放,每次呼叫都會先進行判斷是否已經建立,一旦建立將不會再次建立
正是因為單例的不會被釋放,才有可能造成記憶體風險並且會增加程式的啟動時間。下面是列舉開發中的主要使用場景
- 佇列操作(如日誌和埋點)
- 訪問共享資源(如快取)
- 資源池(執行緒池)
所以在使用單例時候應該基本遵循一下原則:
- 儘量不使用單例
- 儘量避免物件級屬性,儘量使用本地變數
3 依賴注入
依賴注入的本質是在需要的時候傳遞依賴,我們可以先看下下面的例子
- (void)someMethod{ //外部類的方法
XXSomeClass *obj = [XXSomeClass shareInstance]; //單例物件
NSString *someValue = [obj operation:@"some parameter"];
}
很明顯的發現 someMethod依賴了外部的類XXSomeClass,
- 如果XXSomeClass在operation方法中又持有了一些資源,那麼他會一直持有,哪怕shareInstance不會被呼叫。
- 如果XXSomeClass需要在someMethod完成某些初始化,而上游呼叫someMethod的方法並不知道而直接使用XXSomeClass,會造成XXSomeClass並未初始化
這時候就需要依賴注入了,依賴注入可以通過自定義的初始化器或者呼叫方法注入。程式碼如下:
-(instancetype)initWithSomeClass:(XXSomeClass *) someClass{
if(self=[super init]){
self.someClass = someClass;
}
return self;
}
-(void)someMethod{
NSString *someValue = [self.someClass operaion:@"some parameter"];
}
-(void)anotherMethodWithAnotherClass:(anotherClass*) anotherClass{
NSString *someValue = [anotherClass operaion:@"some parameter"];
}
歡迎大家討論一個問題,方法在物件中如何儲存,呼叫過程時如果對方法以及方法中的區域性變數進行管理?