1蒸其、關于nil和Nil及NULL的區(qū)別:
nil: A null pointer to an Objective-C object. ( #define nil ((id)0) ) nil 是一個對象值。
Nil: A null pointer to an Objective-C class.
NULL: A null pointer to anything else. ( #define NULL ((void *)0) ) NULL是一個通用指針(泛型指針)镣奋。
NSNull: A class defines a singleton object used to represent null values in collection objects (which don't allow nil values).
[NSNull null]: The singleton instance of NSNull.
[NSNull null]是一個對象,他用在不能使用nil的場合。
2、避免使用僵尸對象的方法
為了防止不小心調(diào)用了僵尸對象,可以將對象賦值nil(對象的空值)
3岭埠、對象的內(nèi)存泄露
4裹刮、@property 參數(shù)
內(nèi)存管理相關參數(shù):
5音榜、@class的使用
作用
可以簡單地引用一個類
簡單使用
@class Dog; //類的引入
僅僅是告訴編譯器: Dog是一個類; 并不會包含Dog這個類的所有內(nèi)容
具體使用
在.h文件中使用@class引用一個類 在.m文件中使用#import包含這個類的.h文件
通常引用一個類有兩種辦法:
一種是通過#import方式引入;另一種是通過@class引入; 這兩種的方式的區(qū)別在于:
1)#import方式會包含被引用類的所有信息,包括被引用類的變量和方法;@class方式只是告訴 編譯器在A.h文件中 B *b 只是類的聲明,具體這個類里有什么信息,這里不需要知道,等實現(xiàn)文 件中真正要用到時,才會真正去查看B類中信息;
2)使用@class方式由于只需要只要被引用類(B類)的名稱就可以了,而在實現(xiàn)類由于要用到被 引用類中的實體變量和方法,所以需要使用#import來包含被引用類的頭文件;
3)通過上面2點也很容易知道在編譯效率上,如果有上百個頭文件都#import了同一 個文件,或 者這些文件依次被#improt(A->B, B->C,C->D...),一旦最開始的頭文件稍有改動,后面引用到這 個文件的所有類都需要重新編譯一遍,這樣的效率也是可想而知的,而相對來 講,使用@class方 式就不會出現(xiàn)這種問題了;
所以:我們實際開發(fā)中盡量在.h頭文件中使用@class
4)對于循環(huán)依賴關系來說,比方A類引用B類,同時B類也引用A類,B類的代碼:
作用上的區(qū)別
import會包含引用類的所有信息(內(nèi)容), 包括引用類的變量和方法 @class僅僅是告訴編譯器有這么一個類, 具體這個類里有什么信息, 完全不知
效率上的區(qū)別
如果有上百個頭文件都#import了同一個文件,或者這些文件依次被#import,那么一旦最開始的頭 文件稍有改動,后面引用到這個文件的所有類都需要重新編譯一遍 , 編譯效率非常低 相對來講,使用@class方式就不會出現(xiàn)這種問題了
6、循環(huán)引用
循環(huán)retain的場景
比如A對象retain了B對象,B對象retain了A對象 循環(huán)retain的弊端 這樣會導致A對象和B對象永遠無法釋放
循環(huán)retain的解決方案
當兩端互相引用時,應該一端用retain捧弃、一端用assign
7赠叼、NSString 類的內(nèi)存管理問題
1)、NSString 等Foundation框架中類的內(nèi)存管理
先看看以下這幾種寫法:
NSString *testStr1 = @"a";
NSString *testStr2 = [NSString stringWithString:@"a"];
NSString *testStr3 = [NSString stringWithFormat:@"b"];
NSString *testStr4 = [[NSString alloc] initWithString:@"c"];
NSString *testStr5 = [[NSString alloc] initWithFormat:@"d"];
NSString *testStr6 = [[NSString alloc] init];
NSLog(@"testStr1 ->%p",testStr1);
NSLog(@"testStr2 ->%p",testStr2);
NSLog(@"testStr3 ->%p",testStr3);
NSLog(@"testStr4 ->%p",testStr4);
NSLog(@"testStr5 ->%p",testStr5);
NSLog(@"testStr6 ->%p",testStr6);
通過對比地址可以看到,從上可以看出,testStr1,testStr2,testStr4都是在一個內(nèi)存區(qū)域,也 就是常量內(nèi)存區(qū),
1---> NSString *str = [[NSString alloc] initWithString:@"ABC"];
2---> str = @"123";
3---> [str release];
4---> NSLog(@"%@",str);
首先,咱們先對這段代碼進行分析违霞。
第一句 聲明了一個NSString類型的實例 str, 并將其初始化init后賦值為@"ABC" 第二行,將str的指針指向了一個常量@"123"嘴办。 理論上講在第一行初始化的@"ABC"沒有任何任何 指針指向了。 所以造成了內(nèi)存泄露
然后第三行, 將str的引用計數(shù)-1
第四行輸出str的值 為123.
首先回答為什么不會崩潰, 因為第三行的release 實際上是release了一個常量@"123" 而作為 常量,其默認的引用計數(shù)值是很大的(100k+)
NSLog(@"retainCount = %tu",[@"123" retainCount]);
最終的輸出值會是一個很大很大的數(shù)买鸽。 所以單單一個release是不會將其釋放掉的户辞。
然后再回答這樣會不會造成內(nèi)存泄露。
其實............理論上講 會!
但是實際上,Objective-C對NSString類型有特殊照顧癞谒。所有的NSString的引用計數(shù)器默認初始值 都會非常非常大底燎。
2)、危險的用法
while ([a retainCount] > 0) {
[a release];
}
如果運行結果正確,那么這是多么幸運的一個人啊!
8弹砚、自動釋放池及autorelease介紹
自動釋放池
(1)在iOS程序運行過程中,會創(chuàng)建無數(shù)個池子,這些池子都是以棧結構(先進后出)存在的双仍。 (2)當一個對象調(diào)用autorelease時,會將這個對象放到位于棧頂?shù)尼尫懦刂?/p>
自動釋放池的創(chuàng)建方式
(1)iOS 5.0以前的創(chuàng)建方式
NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init];
[pool release];//[pool drain];用于mac
(2)iOS5.0以后
@autoreleasepool
{//開始代表創(chuàng)建自動釋放池
·······
}//結束代表銷毀自動釋放池
#### autorelease
是一種支持引用計數(shù)的內(nèi)存管理方式
它可以暫時的保存某個對象(object),然后在內(nèi)存池自己的排干(drain)的時候對其中的每個 對象發(fā)送release消息 注意,這里只是發(fā)送release消息,如果當時的引用計數(shù)(reference-counted)依然不為0,則該 對象依然不會被釋放∽莱裕可以用該方法來保存某個對象,也要注意保存之后要釋放該對象朱沃。
#### 為什么會有autorelease?
(1)不需要再關心對象釋放的時間
(2)不需要再關心什么時候調(diào)用release
#### autorelease何時釋放?
對于autorelease pool本身,會在如下兩個條件發(fā)生時候被釋放
1)手動釋放Autorelease pool
2)Runloop結束后自動釋放
對于autorelease pool內(nèi)部的對象
在引用計數(shù)的retain == 0的時候釋放。release和autorelease pool 的 drain都會觸發(fā)retain-- 事件。
### 9逗物、Block
一搬卒、靜態(tài)變量和全局變量 在加和不加 __block都會直接引用變量地址。也就意味著可以修
改變量的值翎卓。在沒有加__block 參數(shù)的情況下契邀。
? 全局block和棧block區(qū)別為是否引用了外部變量,堆block則是對棧block copy得來。對全局block
copy 不會有任何作用,返回的依然是全局block失暴。
二, 常量變量(NSString *a = @"hello";a 為常量變量,@“hello”為常量坯门。)-----不 加__block類型 block 會引用常量的地址(淺拷貝)。加__block類型 block會去引用常量變 量(如:a變量,a = @"abc".可以任意修改a 指向的內(nèi)容逗扒。)的地址古戴。