Effective Objective-C 2.0讀書筆記

引子

已經很久沒有看過技術方面的書了,這次難得看了同事推薦的這本《Effective Objective-C 2.0》,適合已經會一點iOS的同學看,我記得我剛踏入這行時買的第一本書是《iOS開發指南》,基本沒看過,所以也不好說那本書寫的怎么樣。下面我先整理一下知識點,最后再說一下心得體會。

一、多用類型常量,少用#define預處理指令

    1. 某個類內的變量。比如:
 #define ANIMATION_DURATION 0.3

可以改寫成

static const NSTimeInterval kAnimationDuration 0.3;

用這種方式的好處是描述了常量的含義,由此知道該常量類型(為NSTimeInterval類型),方便閱讀。注意:若常量為某個類內使用,則需要在前面加字母k。

  • 2.公開某個常量(一般用于通知),可以這樣定義:
//In the header file
extern NSString *const EOCStringConstantNotification;

//In the implemention file
NSString *const EOCStringConstantNotification = @"EOCStringConstantNotification";

即:在.h文件中聲明,在.m實現文件中定義

二、在類繼承體系中查詢類型信息

  • isKindOfClass:能夠判斷出對象是否為某個特定的實例
  • isKindOfClass:能夠判斷出對象是否為某類或其派生類的實例。例如:
//A、B是兩個自定義的類 其中:B繼承自A(A是父類,B是子類)
    [A isMemberOfClass:[A_Object class]];///YES
    [A isMemberOfClass:[B_Object class]];///NO
    [A isKindOfClass:[A_Object class]];///YES
    [A isKindOfClass:[B_Object class]];///YES
    
    [B isMemberOfClass:[A_Object class]];///NO
    [B isMemberOfClass:[B_Object class]];///YES
    [B isKindOfClass:[A_Object class]];///YES
    [B isKindOfClass:[B_Object class]];///YES
注意:書中用了字典和可變字典來舉例子,其實是不準確的。真實打印結果發現如圖所示:
無名

原因是因為其實每個Object-C對象實例都是指向某塊內存數據的指針。而描述Object-C對象所用的數據接口定義在一個結構體里,此結構體內存放類的“元數據”,比如類的實例方法,實例變量之類的,其中首個變量是isa指針,它定義了類對象所屬的類型(也就是isa指針所指向的類型)。super_class指針,定義了本類的超類。而打印dict的isa可以看到,其實本類實例類型其實是“__NSDictionaryM”,并非“NSMutableDictionary”,所以才返回NO,驗證isMemberOfClass和isKindOfClass的異同,最好自定義兩個有繼承關系的類

元數據

三、以弱引用避免保留環

避免保留環的最佳方式就是弱引用。這種引用經常用來表示“非擁有關系”。降屬性聲明為unsafe_unretained即可。另外weak屬性特質與unsafe_unretained的作用完全相同。但weak與unsafe_unretained的區別如下圖所示:


weak與unsafe_unretained

當指向EOCClassA實例的引用移除后,unsafe_unretained屬性仍然指向那個已經回收的實例,而weak屬性則指向nil。

四、以“自動釋放池塊”降低內存峰值

  • 考慮下面這段代碼:
for (int i = 0; i < 100000; i++) {
        [self doSomethingWithInt:i];
    }

如果doSomethingWithInt:方法要創建臨時對象,那么這些對象很可能會放在自動釋放池里。即便這些對象在調用完方法之后就不再使用了,他們也依然處于存活狀態,因為目前還在自動釋放池里,等待系統稍后將其釋放并回收。然而,自動釋放池也要等線程執行下一次事件循環時才會清空。這就意味著在執行for循環時,會持續有新對象創建出來,并加入自動釋放池中,所有這種對象都要等for循環執行完才會釋放。這樣一來,在執行for循環時,應用程序所占內存量就會持續上漲,而等到所有臨時對象都釋放后,內存用量又會突然下降。

比方說,要從數據庫中讀出許多對象。代碼可能會這么寫:

NSArray *datebaseRecords = /*...*/;
    NSMutableArray *people = [NSMutableArray new];
    for (NSDictionary *recode in datebaseRecords) {
        EOCPerson *person = [[EOCPerson alloc]initWithRecord:recode];
        [people addObject:person];
    }

則內存中會有很多不必要的臨時對象,他們本來應該提早回收的,增加一個自動釋放池可以解決此問題。如果把循環內的代碼包裹在“自動釋放池塊”中,那么在循環中自動釋放的對象就會在這個池,而不是線程的主池里面。解決方案如下:

NSArray *datebaseRecords = /*...*/;
    NSMutableArray *people = [NSMutableArray new];
    for (NSDictionary *recode in datebaseRecords) {
        @autoreleasepool {
            EOCPerson *person = [[EOCPerson alloc]initWithRecord:recode];
            [people addObject:person];
        }
    }

五、遍歷

5.1、使用NSEnumerator來遍歷
//遍歷數組,可以這樣寫代碼
NSArray *anArray = /* ... */;
    NSEnumerator *enumerator = [anArray objectEnumerator];
    id object;
    while ((object = [enumerator nextObject]) != nil) {
        //Do something with 'object'
    }
//遍歷字典,可以這樣寫代碼
NSDictionary *anDictionary = /* ... */;
    NSEnumerator *enumerator = [anDictionary keyEnumerator];
    id key;
    while ((key = [enumerator nextObject]) != nil) {
        id value = anDictionary[key];
        //Do something with 'key' and 'object'
    }
  • 這種遍歷的好處:
  • 1.不論遍歷哪種集合,都可以采用這套類似的語法。
  • 2.使用NSEnumerator有多種“遍歷器”(enumerator)可供使用,比如反向遍歷數組所用的枚舉器,NSEnumerator *enumerator = [anArray reverseObjectEnumerator];這樣讀起來更順暢。
5.2、使用for..in 進行遍歷(也可以反向遍歷)
NSArray *anArray = /* ... */;
    for (id object in [anArray reverseObjectEnumerator]) {
        //Do something with 'object'
    }
5.3、基于塊的遍歷方式(本身就通過GCD來并發執行遍歷操作)
//遍歷數組
    NSArray *anArray = /* ... */;
    [anArray enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        //Do something with 'obj'
        if (shouldStop) {
            *stop = YES;
        }
    }];
    //遍歷字典 可以根據條件終止遍歷
    NSDictionary *anDictionary = /* ... */;
    [anDictionary enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        //Do something with 'key' and 'obj'
        if (shouldStop) {
            *stop = YES;
        }
    }];
  • 注意:此遍歷方法也可以反向遍歷- (void)enumerateObjectsUsingBlock:(void (^)(ObjectType obj, NSUInteger idx, BOOL *stop))block;

尾巴

書中還有一些GCD、內存管理,類簇等相關的知識,但本人才疏學淺,不敢吹牛放炮瞎胡造。其實上面的一些東西也是簡單的知識點展示,具體為啥這么用而不那么用那、這么寫好而那么寫不好,還要看書學習,這次權當是為了做一次簡單的知識總結,還有一點心得是:“常立志不如立長志”。多么樸素的道理啊!自己總是既想學這個又想學那個,而且這還不是最糟糕的,最糟糕的是這幾天想學學這個,那幾天又想學學那個,媽蛋的,總是不踏實,希望自己可以踏下心來,鉆研一些東西,下面這句話是中學老師在我改錯本后面寫的一句話,與君共勉:

平常心一個,不平成就得,更勝有心德!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,030評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,310評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,951評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,796評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,566評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,055評論 1 322
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,142評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,303評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,799評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,683評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,899評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,409評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,135評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,520評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,757評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,528評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,844評論 2 372

推薦閱讀更多精彩內容