Objective-C 內(nèi)存管理深入

前言

基礎篇介紹了一些關于Objective-C內(nèi)存管理的常見概念。本文將在前文的基礎上擴展以下知識:成員變量set方法內(nèi)存分析屬性拾徙、屬性特質(zhì)內(nèi)存分析等內(nèi)容,內(nèi)容淺顯易懂感局、屬于學習總結尼啡。如果有需要瀏覽上一篇文章的同學請點擊Objective-C 內(nèi)存管理基礎。希望本文能給正在學習Objective-C的小伙伴們更多啟發(fā)询微。

成員變量的set方法

在屬性(property) 這個語法提出之前崖瞭,iOS開發(fā)者常常這樣構建一個類:

@interface Person : NSObject
{
   NSUInteger _number;
}
- (void)setNumber:(NSUInteger)number;
- (NSUInteger)number;

如上的代碼為Person類添加了一個成員變量_number(添加下劃線是為了命名規(guī)范)。同時手動申明和實現(xiàn)該成員變量的存取方法:setter方法用于寫入值撑毛,getter方法用于讀取值书聚。 這樣的寫法看起來像是一個世紀之前的事情了,但我們能夠從中探究到很多關于內(nèi)存管理方面的問題藻雌。例如:

  • 基本數(shù)據(jù)類型直接賦值
    由于_numberNSUInteger類型雌续,所以其不再內(nèi)存管理的范圍,對于基本類型的setter方法只需要直接賦值就好了胯杭。
    - (void)setNumber:(NSUInteger)number
{
        _number = number;
}
  • ObjC 對象類型需要進行內(nèi)存管理
@class Book;
@interface Person : NSObject
{
    Book *_book;
}
  - (void)setBook:(Book *)book;
  - (Book *)book;

上面的Person類存在一個繼承自NSObject類型的成員變量驯杜,當實現(xiàn)其setter方法時就需要做到以下幾點了。

  • retain 傳入的變量
    根據(jù)內(nèi)存管理原則:“需要持有對象時就對其做一次retain操作”做个。所以應該對傳入的book做一次retain操作鸽心。初步代碼如下:
@implementation Person
    - (void)setBook:(Book *)book
{   
       _book = [book retain]; //持有該對象對book做一次retain操作
}
@end
  • 對象銷毀時 release 其成員變量
    Person對象銷毀時代表_book沒有人使用了滚局,應該在Persondelloc方法里做一次release操作。
@implementation Person
    - (void)setBook:(Book *)book
{   
       _book = [book retain]; //持有該對象對book做一次retain操作
}
    - (void)dealloc
{
       [_book release]; //Person對象銷毀時不再擁有_book顽频,需要對其做一次release操作
       [super dealloc]; 
}
@end
  • ** release 舊的成員變量**
    上面的代碼非常不嚴謹藤肢,因為當出現(xiàn)下面的情況時,舊的成員變量無法被釋放糯景。
  Book *b1 = [Book new];
  [p setBook:b1];
  Book *b2 = [Book new];
  [p setBook:b2];; //重新為_book賦不同的值
  [b2 release];
  [b1 release];

由于setter方法對傳入的b1嘁圈、b2都做了一次retain,在Person對象的delloc方法里卻只對當前的_book(也就是b2) release蟀淮,導致舊的成員變量b1無法被釋放丑孩,由此產(chǎn)生了內(nèi)存泄露問題。對setter方法優(yōu)化后的代碼應該如下:

    - (void)setBook:(Book *)book
{
      [_book release]; //對原來使用的成員變量做一次release操作
      _book = [book retain]; //再持有新傳入的變量
}  
  • 判斷傳入的變量
    即便是上面的代碼仍然還有問題灭贷,比如:
   Person *p = [Person new];
   Book *b1 = [Book new];
   [p setBook:b1];
   [b1 release];
   [p setBook:b1];; //對_book 重新賦相同的值
   [p release];

[b1 release]代碼執(zhí)行完畢,b1的引用計數(shù)器值為 1 略贮,接著執(zhí)行[p setBook:b1]p.book重新賦相同的值時甚疟,會進行下面的操作:

     [_book release]; 
     _book = [book retain];

【注意】:此時的_book是第一次設置的變量b1,其引用計數(shù)器值為1逃延;再進行release览妖,變量b1的引用計數(shù)變?yōu)?,系統(tǒng)回收該對象內(nèi)存揽祥;接著執(zhí)行
_book = [book retain]將發(fā)生錯誤讽膏,因為此時的b1已經(jīng)是僵尸對象retain無法將一個僵尸對象起死回生(需要開啟僵尸對象檢測功能)拄丰。
【解決方案】:應該對傳入的變量(book)進行判斷府树,如果傳入的變量(book)和當前成員變量(_book)是同一個變量,那么setter方法不需要做任何操作料按。

最后的一個完整的setter方法應該如下:

  - (void)setBook:(Book *)book
{
       if (book != _book) {      //兩者進行判斷
          [_book release];       //對原來的成員變量進行release
          _book = [book retain]; //對傳入的變量進行retain
       }
}

屬性

屬性(property)是Objective-C 2.0引入的新特性奄侠,其通過將成員變量包裝達到封裝對象中數(shù)據(jù)的作用,并且提供了“點語法”使開發(fā)者更簡單的依照類對象訪問其中的數(shù)據(jù)载矿。具體來說使用屬性構建類主要有以下好處:

  • 自動合成存取方法
    使用屬性封裝數(shù)據(jù)可以讓編譯器自動申明和實現(xiàn)與屬性相關的存取方法垄潮,此過程有一個專業(yè)名稱--“自動合成”(synthesize)。而且該過程是在編譯執(zhí)行的期間自動完成的闷盔,因此無法看到 “合成方法(synthesized method)”的源碼弯洗。
@class Book;
@interface Person : NSObject
@property Book *book;
@end
@class Book;
@interface Person : NSObject
{
      Book *_book;
}
    - (void)setBook:(Book *)book;
    - (Book *)book;

上面兩段代碼實際上是等效的。

  • 自動生成對應的成員變量
    除了自動生成方法代碼外逢勾,編譯器還會自動向類中添加屬性對應的成員變量牡整,并且在屬性名前面加上下劃線,以此作為成員變量的名稱并和屬性名區(qū)分開來溺拱。
    - (void)dealloc
{
      [_book release];
      NSLog(@"Person - dealloc");
      [super dealloc];
}

在上面使用屬性語法的Person類中果正,重寫dealloc能調(diào)用[_book release]說明的確是生成了屬性對應的成員變量_book炎码。

  • 支持自定義成員變量名
    如果開發(fā)中對編譯器自動生成的成員變量名不滿意贡定,使用@synthesize語法在類的實現(xiàn)文件里可以自定義其名稱棠枉。
    注意:該語法是將已經(jīng)存在的屬性名替換成左邊自定義的名稱,以后屬性對應的系統(tǒng)生成的帶有下劃線的成員變量名就被替換成了自定義的名字哨免。同時其存取方法中使用到的成員變量名也將被替換迫皱。但是通過點語法調(diào)用self.property是不受影響的歉闰。
@implementation Person
@synthesize book = _myBook;
 //自定義的_myBook名稱用來替換之前的屬性名稱,
//但是通過點語法調(diào)用self.book是不受影響的卓起。
    - (void)dealloc
{
      [_myBook release];
      // [self.book release]; 這行代碼和上面那行代碼是一樣的和敬。
      NSLog(@"Person - dealloc");
      [super dealloc];
}
@end
  • 支持自定義成員變量存取方法
    1,如果通過屬性語法自動生成的getter戏阅、setter方法不能滿足開發(fā)要求昼弟,我們可以重寫屬性對應的gettersetter方法奕筐,達到自定義存取方法的目的舱痘。
    2,使用dynamic關鍵字离赫,該語法告知編譯器不要為某些屬性創(chuàng)建對應的成員變量和默認實現(xiàn)的存取方法(這樣做的后果是屬性對應的成員變量和其存取方法都需要自己定義和實現(xiàn))芭逝。
@implementation Person
@dynamic book;
    - (void)dealloc
{
      [_book release]; //此行代碼報錯,具體原因為_book成員變量沒有申明
      NSLog(@"Person - dealloc");
      [super dealloc];
}
@end

通過上面的解釋我們得出這樣的結論:
屬性 = 成員變量 + 存取方法 (@property = ivar + getter + setter)

屬性語法極大的簡化了開發(fā)人員在構建類時封裝數(shù)據(jù)的工作量(編譯器默認實現(xiàn))渊胸。另外需要注意的是 synthesize旬盯、**dynamic **關鍵字用的較少,因為大部分時候編譯器默認實現(xiàn)的代碼還是比較符合開發(fā)需求的翎猛。


屬性特質(zhì)內(nèi)存分析

在上面講解屬性特性時申明的屬性胖翰,仍然是不符合要求的。

@class Book;
@interface Person : NSObject
@property Book *book;
@end

這樣的定義的屬性切厘,其setter方法僅僅類似于普通的基本數(shù)據(jù)類型直接賦值泡态,驗證代碼如下:

 Person *p = [Person new];
 Book *b = [Book new];
 p.book = b;
  NSLog(@"%lu",b.retainCount); //打印b的引用計數(shù)器值為 1 
 [b release];
 [p release];

通過打印b的引用計數(shù)器值(b.retainCount = 1),我們發(fā)現(xiàn)代碼p.book = b執(zhí)行后迂卢,b的引用計數(shù)并沒有增加某弦;如果此時進行的是“處理過的setter方法”,b必定會被retain一次而克,其引用計數(shù)值應該為2靶壮,所以得出結論:單純的@property Book *book定義屬性,其setter方法只是進行了簡單的賦值運算员萍,并不符合Objc對象需要進行內(nèi)存管理的原則腾降。因此在MRC中我們常常這樣改進:

@class Book;
@interface Person : NSObject
@property (retain) Book *book;
@end

通過使用retain編譯器會將該屬性對應的setter方法替換成上面提到的 “完整的setter方法”,進而解決內(nèi)存管理問題碎绎。 在ARC中對于屬性后面的修飾詞處理的更加嚴謹和豐富螃壤,具體來說引入了 屬性特質(zhì)(attributes)概念抗果。

  • 屬性特質(zhì)(attributes)
    屬性特質(zhì)(attributes)也可被稱為屬性修飾詞屬性特性奸晴。通過分析源碼可以一探究竟冤馏。
    propertyruntime中是objc_property_t,其結構如下:
typedef struct objc_property *objc_property_t;

objc_property是一個結構體寄啼,包括nameattributes逮光,其結構如下:

struct property_t {
    const char *name;
    const char *attributes;
};

attributes本質(zhì)是objc_property_attribute_t,定義了property的一些特性墩划,其結構如下如下:

typedef struct {
    const char *name;           /**< The name of the attribute */
    const char *value;          /**< The value of the attribute (usually empty) */
} objc_property_attribute_t;

attributes主要描述特性有:原子性和非原子性涕刚、讀寫權限、存取方法名乙帮、內(nèi)存管理語義等杜漠。

  • 修飾詞對內(nèi)存的影響(ARC)

  • 原子性
    atomic:原子性的(編譯器默認該特性)。該特性會為屬性的setter方法加鎖察净,以保證其操作是線程安全的驾茴,同時會影響性能。

    nonatomic:非原子性的塞绿。該特性不會為屬性的setter方法加鎖,非線程安全的恤批,但是能極大的提升性能异吻。由于在iOS開發(fā)中移動設備性能有限,所以絕大多數(shù)情況下使用的該特性喜庞。

    iOS中使用同步鎖的開銷加大诀浪,這會帶來性能問題。一般情況下并不要求屬性必須是“原子性”的延都,因為這并不能保證線程安全雷猪。若要實現(xiàn)“線程安全”的操作,還需采用更深層的鎖定機制才行晰房。開發(fā)iOS程序是一般都會使用nonatomic特性求摇,因為atomic會嚴重影響性能,但是在開發(fā)Mac OS X 程序時殊者,使用atomic不會有性能瓶頸与境。

  • 讀寫權限

readwrite:可讀可寫的(編譯器默認該特性)。該特性表明編譯器會為其生成對應的gettersetter方法猖吴。同時你可以設置和讀取該值摔刁。

readonly:只讀的。該特性修飾的屬性你將不能直接修改其值海蔽,例如使用點語法賦值時報錯共屈,提示不能為readonly 的屬性賦值(但是可以通過KVC機制為該屬性賦值)绑谣。

  • 內(nèi)存管理語義

    assign:直接賦值。用于Objective-C中基本數(shù)據(jù)類型的變量作為屬性拗引,該特性修飾的屬性其setter方法只會針對“純量類型”進行簡單的賦值操作借宵。例如枚舉類型、布爾類型寺擂、整型暇务、浮點型等基本數(shù)據(jù)類型的變量(基本數(shù)據(jù)類型變量無需內(nèi)存管理)。

    weak:非持有關系 怔软。用于Objective-C中對象作為屬性垦细。同assign類似該特性修飾的屬性其setter方法既不保留新值,也不釋放舊值挡逼;然而在屬性所指的對象銷毀時括改,屬性值會被清空。

    ARC下家坎,在有可能出現(xiàn)循環(huán)引用情況中往往要通過讓其中一端使用weak來解決嘱能,比如:兩個類相互為對方的屬性、申明delegate代理屬性等虱疏。另外自身已經(jīng)對它進行一次強引用惹骂,沒有必要再強引用一次,此時也會使用weak做瞪,比如:添加子控件是常常用到[self.view addSubView: self.imageView]对粪;self.imageView這個屬性就可以使用weak定義。xib中拖線時IBOutlet控件屬性一般也使用weak(當然装蓬,也可以使用strong)著拭。

    如果你對 “屬性所指的對象銷毀時,屬性值會被清空”不是很理解牍帚,可以參考下面的例子:

@interface ViewController ()
@property (nonatomic, weak) UIView *redView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIView *redView = [[UIView alloc] init]; //創(chuàng)建子視圖
redView.backgroundColor = [UIColor redColor]; //設置子視圖背景色
[self.view addSubview:redView]; //添加到視圖上
self.redView = redView; //屬性賦值
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
NSLog(@"%@",self.redView);
self.redView.frame = CGRectMake(50, 50, 100, 100); //點擊屏幕設置尺寸
}
@end

     【分析】示例代碼將`redView`添加的控制器的`View`上儡遮,當用戶點擊屏幕的時候設置其尺寸顯示出來。對于一般繼承自`NSObject`類型的變量作為屬性時通常使用`strong`修飾暗赶。這里的`redView`明顯是對象類型鄙币,其使用`weak`修飾是因為`[self.view addSubview:redView]`該行代碼將`redView `作為一個元素加入到`self.view.subviews`數(shù)組中,`self.view`本身隱式的對`redView `做了一次持有操作蹂随。

    (1)當將`[self.view addSubview:redView]`代碼注釋爱榔。

    控制臺輸出:`self.redView = (null)`

    【分析】`self.view`未對`self.redView`進行持有操作(`weak`修飾只是簡單的賦值,未對傳入的變量進行`retain`)糙及,當`viewDidLoad `方法調(diào)完详幽,系統(tǒng)為`UIView`對象在堆區(qū)分配出來的空間(`[[UIView alloc] init]`)就被回收了,所以此時`self.redView`指向的對象已經(jīng)被銷毀,同時由于其是`weak`修飾唇聘,編譯器將其指向`nil`版姑,所以打印`self.redView`時其值為`null`。

    (2)如果此時將`redView`聲明為`assign`修飾迟郎,即:

@property (nonatomic, assign) UIView *redView;

點擊屏幕時就會崩潰剥险。
![壞內(nèi)存訪問錯誤](http://upload-images.jianshu.io/upload_images/2474121-15ca43eb54eabcc3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

    【分析】在屬性所指的對象銷毀時,`assign`不會將屬性指向`nil`宪肖,所以此時`self.redView`已經(jīng)是一個野指針其指向了一個僵尸對象表制,打印`self.redView`時訪問了一塊已經(jīng)被回收的內(nèi)存。所以崩潰控乾。
希望能通過這個簡單的例子解釋一下`weak`和`assign`的區(qū)別么介。

   **unsafe_unretained:**非持有關系(同`assign`)。用于Objective-C中對象或者是基本數(shù)據(jù)類型的變量作為屬性蜕衡。同`weak`一樣該特性修飾的屬性其`setter`方法既不保留新值(`unretained`)壤短,也不釋放舊值。不同的是如果屬性所指的對象被銷毀慨仿,指向該對象的指針依然指向原來的內(nèi)存地址久脯,如果此時繼續(xù)訪問該對象很容易產(chǎn)生壞內(nèi)存訪問/野指針/僵尸對象訪問(`unsafe`)。

    **strong:**持有關系镰吆。用于Objective-C中對象作為屬性帘撰。該特性修飾的屬性的`setter`方法會對傳入變量做一次`retain`并對之前的成員變量做一次`release`。其作用和MRC下的`retain`操作是一樣的万皿。

   **copy:**拷貝關系摧找。`copy` 的作用與`strong`類似,然而其修飾的屬性的`setter`方法并非`retain`新值相寇,而是將其“拷貝” (`copy`)一份慰于。因為父類指針可以指向子類對象(多態(tài)性)钮科,使用`copy`的目的是為了讓本對象的屬性不受外界影響唤衫,無論給對象傳入是一個可變對象還是不可對象,對象本身持有的就是一個不可變的副本绵脯。

    >定義`NSString`佳励、`NSArray`、`NSDictionary`等類型的變量作為屬性時常使用`copy`關鍵字蛆挫, 因為其有對應的可變類型:
`NSMutableString`赃承、`NSMutableArray`、`NSMutableDictionary`(可變類型用`strong`)悴侵。
開發(fā)中常用的`block`代碼塊習慣使用`copy`關鍵字修飾(`strong`也是可以的)瞧剖。

  * **存取方法名**
 **getter = <name>:**通常在為類定義布爾類型的屬性時用于自定義其`getter`方法名。例如:

/// 是否正在工作
@property (nonatomic, assign, getter=isWorking) BOOL working;
/// 是否有訂單有顯示中
@property (nonatomic, assign, getter=isShowing) BOOL showing;


   **setter = <name>:**該修飾詞極少使用,除非特殊情況下抓于,例如:
>在數(shù)據(jù)反序列化做粤、轉(zhuǎn)模型的過程中,服務器返回的字段如果以`init`開頭捉撮,所以你需要定義一個`init`開頭的屬性怕品,但默認生成的`setter`與`getter`方法也會以`init`開頭,而編譯器會把所有以`init`開頭的方法當成初始化方法巾遭,而初始化方法只能返回`self`類型肉康,因此編譯器會報錯。這時你就可以使用下面的方式來避免編譯器報錯:

@property(nonatomic, copy, getter=p_initBy, setter=setP_initBy:) NSString *initBy;


  * **空值約束(iOS9推出的新特性)**

   **nullable:**該屬性值可以為空灼舍。用于Objective-C中對象作為屬性吼和,表示該屬性的`getter`和`setter`方法中賦值和取值都是可以為空。
盡管在定義屬性時寫或不寫`nullable `對該屬性的賦值和操作沒有任何影響片仿,但寫上`nullable `更多的作用在于程序員之間的溝通交流纹安,時刻提醒開發(fā)人員該屬性不一定是有值的,可能需要空值判斷砂豌,要注意使用厢岂。 

    **nonnull:**該屬性值不能為空。和`nullable `對立阳距,該特質(zhì)修飾的屬性其`getter`和`setter`均不能為空值塔粒,否則會有警告。
另外下面的寫法是等價的筐摘。

@property (nonnull卒茬,nonatomic, copy) NSArray *array;
@property (nonatomic, copy) NSArray * __nonnull array1;


    `nullable`、`nonnull`除了在定義屬性時使用咖熟,還可以用在函數(shù)和方法中對參數(shù)和返回值的空值進行約束圃酵。例如:

//函數(shù)
void text(NSArray * __nonnull array) {
}
//方法
- (NSString *__nonnull)creat:(NSArray * __nonnull)array {
return @"coderYQ";
}

![nullable和nonnull的使用](http://upload-images.jianshu.io/upload_images/2474121-8cb863891576d6cc.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

    當然如果你嫌麻煩,還可以使用宏一次性聲明:

NS_ASSUME_NONNULL_BEGIN
@interface ViewController ()
@property (nonatomic, copy) NSArray *array;
@property (nonatomic, copy) NSArray *array1;
@property (nonatomic, copy) NSArray *array2;
@end
NS_ASSUME_NONNULL_END

如此兩個宏`NS_ASSUME_NONNULL_BEGIN `馍管、`NS_ASSUME_NONNULL_END `之間定義的屬性均有`nonnull `提示郭赐,當然你也可以修改其中的約束,例如:

NS_ASSUME_NONNULL_BEGIN
@interface ViewController ()
@property (nullable, nonatomic, copy) NSArray *array;
@property (null_resettable, nonatomic, copy) NSArray *array1;
@property (nonatomic, copy) NSArray *array2;
@end
NS_ASSUME_NONNULL_END


    **null_resettable:**該特性修飾的屬性表示其`setter`中可以賦值為空确沸,但是`getter`方法中返回的值不會為空捌锭。使用該特性定義屬性時編譯器會提出警告:

    應該重寫`setter`方法處理賦值為空的情況。
    ![null_resettable的使用](http://upload-images.jianshu.io/upload_images/2474121-72ca8eb876123438.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
一個`null_resettable `經(jīng)典的使用示例就是蘋果定義`UIViewController`的`view`屬性:

@property(null_resettable, nonatomic,strong) UIView *view;

![null_resettable的使用](http://upload-images.jianshu.io/upload_images/2474121-c61f1fc4a4261aab.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

   大家都知道控制器的`view`是懶加載的罗捎,每次調(diào)用`getter`方法一旦發(fā)現(xiàn)`view`屬性為空观谦,系統(tǒng)會調(diào)用`loadView`方法創(chuàng)建并返回`view`。該關鍵字告訴開發(fā)人員`self.view`是永遠不會為空的 桨菜,你可以放心的使用豁状。

  由于在構建類時為其定義的各種屬性有不同的類型捉偏,所以可以通過屬性修飾詞對存取方法進行微調(diào)進而滿足內(nèi)存管理規(guī)范。
>但是開發(fā)中有時候會重寫`getter`或`setter`方法泻红。這時我們應該保證實現(xiàn)的方法是具備相關屬性的特質(zhì)告私。例如將某個屬性申明為`copy`,那么重寫`setter`方法時應該拷貝傳入的對象承桥,否則誤導該屬性的使用者驻粟,嚴重時會產(chǎn)生bug。同理在其他方法中設置屬性值時凶异,也需要遵循屬性修飾詞的規(guī)定蜀撑。

  例如:在下面的自定義初始化方法中`name`應該使用`copy`,而`age`則直接賦值剩彬。

@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) int age;

  • (instancetype)initWithName:(NSString *)name
    age:(int)age;
    @end

@implementation Person

  • (instancetype)initWithName:(NSString *)name age:(int)age
    {
    if (self = [super init]) {
    _name = [name copy];
    _age = age;
    }
    return self;
    }
    @end

---
##屬性和成員變量的選擇使用
在上面的`- (instancetype)initWithName: age:`初始化方法中酷麦,初學者可能會有疑問為什么使用的`_name`成員變量而不是`self.name`屬性呢?這里本人通過查閱《Effective Objective-C 2.0 編寫高質(zhì)量iOS與OS X代碼的52個有效方法》對屬性和成員變量的使用場景做了一些總結:

 * 初始化方法中設置屬性值時使用成員變量喉恋,因為子類可能會覆蓋該屬性的`setter`方法沃饶。例如:
  • (instancetype)initWithName:(NSString *)name age:(int)age
    {
    if (self = [super init]) {
    _name = [name copy];
    _age = age;
    }
    return self;
    }

 * 懶加載方法中使用成員變量初始化,并通過屬性訪問轻黑。例如:
  • (Book *)book
    {
    if (!_book) {
    _book = [[Book alloc] init];
    }
    return _book;
    }

self.book //懶加載的屬性必須通過“getter”方法訪問糊肤,否則成員變量永遠不會被初始化
因為若沒有使用getter方法直接訪問成員變量(_book),該成員變量(_book)此時尚未設置完成氓鄙。

 * 在`delloc`方法中使用成員變量
  • (void)dealloc
    {
    [_book release];
    [super dealloc];
    }

* 在對象內(nèi)部盡量直接訪問成員變量

關于屬性和成員變量使用的更多細節(jié)請閱讀《Effective Objective-C 2.0 編寫高質(zhì)量iOS與OS X代碼的52個有效方法》第6馆揉、7條。

##文章最后
以上就是筆者對于Objective-C內(nèi)存管理深入知識的學習總結抖拦,部分描述引自《Effective Objective-C 2.0 編寫高質(zhì)量iOS與OS X代碼的52個有效方法》這里做出說明升酣。

如果文中有任何紕漏或錯誤歡迎在評論區(qū)留言指出,本人將在第一時間修改過來态罪;喜歡我的文章噩茄,可以關注我以此促進交流學習; 如果覺得此文戳中了你的G點請隨手點贊复颈;轉(zhuǎn)載請注明出處绩聘,謝謝支持。
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末券膀,一起剝皮案震驚了整個濱河市君纫,隨后出現(xiàn)的幾起案子驯遇,更是在濱河造成了極大的恐慌芹彬,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件叉庐,死亡現(xiàn)場離奇詭異舒帮,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門玩郊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來肢执,“玉大人,你說我怎么就攤上這事预茄〕苌拢” “怎么了刨沦?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵召庞,是天一觀的道長篮灼。 經(jīng)常有香客問我,道長逢艘,這世上最難降的妖魔是什么它改? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任鹉戚,我火速辦了婚禮抹凳,結果婚禮上失都,老公的妹妹穿的比我還像新娘咳焚。我一直安慰自己革半,他們只是感情好,可當我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著觉阅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪割笙。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天宫静,我揣著相機與錄音伏伯,去河邊找鬼。 笑死蜓堕,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的背伴。 我是一名探鬼主播携兵,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼拂檩!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起嘲碧,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤愈涩,失蹤者是張志新(化名)和其女友劉穎糠聪,沒想到半個月后身害,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體丙猬,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年茧球,在試婚紗的時候發(fā)現(xiàn)自己被綠了弹灭。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡揪垄,死狀恐怖穷吮,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情饥努,我是刑警寧澤捡鱼,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站酷愧,受9級特大地震影響堰汉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜伟墙,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一翘鸭、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧戳葵,春花似錦就乓、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至戏自,卻和暖如春邦投,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背擅笔。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工志衣, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人猛们。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓念脯,卻偏偏與公主長得像,于是被迫代替她去往敵國和親弯淘。 傳聞我的和親對象是個殘疾皇子绿店,可洞房花燭夜當晚...
    茶點故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容

  • iOS開發(fā)中, 之前一直使用swift, 因此對于Objective-C的內(nèi)存管理機制長期處于混亂的一知半解狀態(tài)....
    icetime17閱讀 844評論 1 8
  • Objective-C 1. import的用法 拷貝文件內(nèi)容可以自動防止文件的內(nèi)容被重復拷貝(#define宏定...
    馬文濤閱讀 5,338評論 3 17
  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結起來就是把...
    Dove_iOS閱讀 27,139評論 30 470
  • 跟你一起其實是個意外。從沒想過我們會一起走這么長時間,結婚假勿、生子借嗽、生活、奮斗…… 也許愛情里不僅有一見鐘情转培、更多的...
    紫mum閱讀 178評論 0 0
  • “對了恶导,聊了這么久還不知道小兄弟來這里做什么呢?”刀疤爽朗的問道堡距,蕭峰沉思了會回道:“大哥甲锡,你也別小兄弟這么叫了兆蕉,...
    一點鑰匙閱讀 172評論 0 0