1. 在 dealloc 只釋放引用并解除監(jiān)聽(tīng)
永遠(yuǎn)不要自己去調(diào)用dealloc
. 運(yùn)行期系統(tǒng)會(huì)在合適的時(shí)候調(diào)用, 根據(jù)性能需求我們需要在里面實(shí)現(xiàn)一些操作, 那么我們可以在dealloc
里做些什么呢?
- 釋放對(duì)象所擁有的所有引用, 不過(guò)ARC會(huì)自動(dòng)添加這些代碼, 不用擔(dān)心
- 對(duì)象擁有的其他非OC對(duì)象也需要釋放(
CoreFoundation
對(duì)象就必須手動(dòng)釋放)\ - 釋放原來(lái)的觀測(cè)行為: 注銷通知, 如果沒(méi)有及時(shí)注銷,就會(huì)向其發(fā)送通知, 可能導(dǎo)致程序崩潰.
舉個(gè)簡(jiǎn)單例子:
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
尤其注意:
在dealloc
中不要調(diào)用其他方法, 因?yàn)檫@些方法都是異步的, 在回調(diào)方法中還要使用這些方法 那么很有可能當(dāng)前對(duì)象已經(jīng)被釋放了, 會(huì)導(dǎo)致程序崩潰.
2. 多用塊枚舉, 少用for循環(huán)
當(dāng)遍歷數(shù)據(jù)元素時(shí), 建議使用塊枚舉, 因?yàn)橄鄬?duì)于傳統(tǒng)的for循環(huán), 枚舉更加高效, 而且簡(jiǎn)潔, 還能獲取到用產(chǎn)痛for循環(huán)無(wú)法提供的值.
我們先看一下傳統(tǒng)的for循環(huán)遍歷
傳統(tǒng)for循環(huán)遍歷
NSArray *anArray = /* ... */;
for (int i = 0; i < anArray.count; i++)
{
id object = anArray[i];
// Do something with 'object'
}
// Dictionary
NSDictionary *aDictionary = /* ... */;
NSArray *keys = [aDictionary allKeys];
for (int i = 0; i < keys.count; i++)
{
id key = keys[i];
id value = aDictionary[key];
// Do something with 'key' and 'value'
}
// Set
NSSet *aSet = /* ... */;
NSArray *objects = [aSet allObjects];
for (int i = 0; i < objects.count; i++)
{
id object = objects[i];
// Do something with 'object'
}
我們可以看到, 在遍歷Dictionary 和 Set 的時(shí)候, 用創(chuàng)建了數(shù)組, 雖然我們使用for循環(huán)遍歷達(dá)到了我們的目的, 但卻加大了系統(tǒng)的開(kāi)銷.
采用快速遍歷
NSArray *anArray = /* ... */;
for (id object in anArray)
{
// Do something with 'object'
}
// Dictionary
NSDictionary *aDictionary = /* ... */;
for (id key in aDictionary)
{
id value = aDictionary[key];
// Do something with 'key' and 'value'
}
NSSet *aSet = /* ... */;
for (id object in aSet)
{
// Do something with 'object'
}
這種快速遍歷要比傳統(tǒng)遍歷要簡(jiǎn)介易懂, 但缺點(diǎn)是無(wú)法方便獲取數(shù)組的下標(biāo).
利用基于塊(block)的遍歷
NSArray *array = @[@"a", @"b", @"c", @"d"];
[array enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
// Do something with 'objece'
if (@"b")
{
*stop = YES;//使迭代停
}
}];
//Dictionary
NSDictionary *dic = @{@"a":@"1", @"b":@"2", @"c":@"3"};
[dic enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
//Do something with 'key' and 'obj'
if (@"b") {
*stop = YES;//使迭代停止
}
}];
//Set
NSSet *set = [NSSet setWithObjects:@"a", @"b", @"c", @"d", nil];
[set enumerateObjectsUsingBlock:^(id _Nonnull obj, BOOL * _Nonnull stop) {
//Do something with 'obj'
if (@"b") {
*stop = YES;//使迭代停止
}
}];
我們可以看到载庭,在使用塊進(jìn)行快速枚舉的時(shí)候蜀涨,我們可以不創(chuàng)建臨時(shí)數(shù)組佩脊。雖然語(yǔ)法上沒(méi)有快速枚舉簡(jiǎn)潔,但是我們可以獲得數(shù)組元素對(duì)應(yīng)的序號(hào),字典元素對(duì)應(yīng)的鍵值,而且陶夜,我們還可以隨時(shí)令遍歷終止。
利用快速枚舉和塊枚舉還有一個(gè)優(yōu)點(diǎn), 能夠修改塊的方法簽名
for (NSString *key in aDictionary)
{
NSString *object = (NSString*)aDictionary[key];
// Do something with 'key' and 'object'
}
NSDictionary *aDictionary = /* ... */;
[aDictionary enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop)
{
// Do something with 'key' and 'obj'
}];
如果我們可以知道集合里的元素類型裆站,就可以修改簽名条辟。這樣做的好處是:可以讓編譯期檢查該元素是否可以實(shí)現(xiàn)我們想調(diào)用的方法黔夭,如果不能實(shí)現(xiàn),就做另外的處理羽嫡。這樣一來(lái)本姥,程序就能變得更加安全。
3. initialize 與 load 實(shí)現(xiàn)代碼
load 方法
+ (void)load
每個(gè)類和分類在運(yùn)行期時(shí)都會(huì)調(diào)用 load
方法, 而且僅僅調(diào)用一次, 很多小伙伴喜歡在這里調(diào)用一些方法, 作者建議盡量不要在這里調(diào)用其他方法,尤其是使用其他的類杭棵。因?yàn)槊總€(gè)類載入程序庫(kù)的時(shí)機(jī)是不同的,如果該類調(diào)用了載入程序庫(kù)的類, 就會(huì)很危險(xiǎn).
initialize方法
+ (void) initialize;
這個(gè)類方法與load
方法相似,區(qū)別是這個(gè)方法在程序首次調(diào)用這個(gè)類的時(shí)候調(diào)用(惰性調(diào)用),而且只調(diào)用一次(絕對(duì)不能主動(dòng)使用代碼調(diào)用).
下面看一下代碼執(zhí)行順序:
舉個(gè)例子:
+ (void)load
{
NSLog(@"%@ load", self);
}
+ (void)initialize
{
NSLog(@"%@ initialize", self);
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"123456789");
}
控制臺(tái)打印結(jié)果
**2016-10-28 17:02:24.813 Practise[98589:1255983] ViewController initialize
**2016-10-28 17:02:24.815 Practise[98589:1255983] ViewController load
**2016-10-28 17:02:24.905 Practise[98589:1255983] 123456789