Effective Objective-C 2.0 無廢話精簡篇

1. 了解 Objective-C 語言的起源

Objective-C 語言使用”消息結(jié)構(gòu)”而非”函數(shù)調(diào)用”.Objective-C 語言由 Smalltalk演化而來,后者是消息類型語言的鼻祖.編譯器甚至不關(guān)心接收消息對象的何種類型.接收消息的對象問題也要在運(yùn)行時處理,其過程叫做”動態(tài)綁定”.
Objective-C為 C 語言添加了面向?qū)ο筇匦?是其超類. Objective-C 使用動態(tài)綁定的消息結(jié)構(gòu),也就是說,在運(yùn)行時才會檢查對象類型.接收一條消息后,究竟應(yīng)執(zhí)行何種代碼,有運(yùn)行期環(huán)境而非編譯器決定.理解 C 語言的核心有助于寫好 Objective-C 程序.尤其是掌握內(nèi)存模型與指針.

2. 在類的頭文件中盡量少引用其他頭文件

Objective-C 語言編寫類的標(biāo)準(zhǔn)行為:以類名做文件名,分別闖將兩個文件,有文件后綴用. h,實現(xiàn)文件后綴用. m.
在開發(fā)中有時候我們會在. h 文件中引入很多用不到的內(nèi)容,這當(dāng)然會增加編譯時間.除非有必要,否則不要引入頭文件,一般來說,某個類的頭文件中使用向前聲明來體積別的類,并在實現(xiàn)文件中引入哪些類的頭文件,這樣做可以盡量降低類之間的耦合.有時無法使用前聲明,比如要聲明某個類遵循意向協(xié)議,這種情況下,盡量把 “該類遵循某協(xié)議”的這條聲明移至 class=continuation 分類中,如果不行的話,就把協(xié)議單獨(dú)存放在一個頭文件中,然后將其引入.

3. 多用字面量語法,少用與之等價的方法
NSArray *arr = [NSArray arrayWithObjects:@"num1",@"num2",@"num3", nil];
NSArray *arr = @[@"num1",@"num2",@"num3”];

字面量語法創(chuàng)建字符串,數(shù)組,數(shù)值,字典.與穿件此類對象的常規(guī)方法相比,這么做更加簡明扼要.

注意事項:

  • 除了字符串以外,所創(chuàng)建的類必須屬于 Foundation 框架才行,如果自定義了這些類的子類,則無法用字面量語法創(chuàng)建其對象.
  • 穿件的數(shù)組或字典時,若值有 nil, 則會拋出異常.因此,務(wù)必確保值中不含 nil.
4. 多用類型常量,少用# deine 預(yù)處理指令

不要用預(yù)處理指令定義常量,這樣定義出來的常量不含類型信息,編譯器只會在編譯前根據(jù)執(zhí)行查找與替換操作,即使有人重新定義了常量值,編譯器也不會產(chǎn)生井道信息,這將導(dǎo)致應(yīng)用程序常量值不一致.

static NSString *const PersonConstant = @"PersonConstantStr” ;

但是我個人認(rèn)為其實,還是#define用的多, 開發(fā)避免不了使用 pch文件. 如果有強(qiáng)迫癥的同學(xué),定義常量就想使用 staitc,extren,const這些關(guān)鍵字.那我建議新建一個專門存放這些常量的類,然后在 pch 中導(dǎo)入這個類.

  • static 修飾符意味著該變量盡在定義此變量的單元中可見
  • extern 全局變量
Person.h
#import <Foundation/Foundation.h>
static NSString *const PersonConstant;
@interface Person : NSObject
@end

Person.m
#import "Person.h"
static NSString *const PersonConstant = @"PersonConstantStr";
@implementation Person
@end

.pch
#define DefineStr @"DefineStr"
#import "Person.h"
#endif
5. 用枚舉表示狀態(tài),選項,狀態(tài)碼

應(yīng)該用枚舉來表示狀態(tài)機(jī)的狀態(tài),傳遞給方法的選項以及狀態(tài)碼等值,給這些值起個易懂的名字

enum PersonEnum{
    PersonEnumNum1,
    PersonEnumNum2,
    PersonEnumNum3,
};
typedef enum PersonEnum PersonState;
6. 理解屬性這一概念

屬性是 Objective-C 的一項特性,用于封存對象中的數(shù)據(jù).
屬性特質(zhì):原子性 讀寫權(quán)限
內(nèi)存管理語義

  • assign 這是方法只會執(zhí)行針對純量類型(CGFloat,NSInteger)的簡單賦值操作
  • strong 此特質(zhì)表明該屬性定義一種擁有關(guān)系,為這種屬性設(shè)置新值時,這只方法會先保存新值,并釋放舊值
  • weak 此特質(zhì)表明屬性定義了一種”非擁有關(guān)系”,為這種屬性設(shè)置新值是,設(shè)置方法既不保留新值,也不釋放舊值.此特質(zhì)同 assign 類似,然而在屬性所指對象遭到摧毀時,屬性值會清空
  • unsafe_unretainde 此特質(zhì)與 assign 相同,它適用于對象類型,該特質(zhì)表達(dá)一種"非擁有關(guān)系”,當(dāng)目標(biāo)對象遭到摧毀時,屬性不會自動清空,因為它是不安全的,這一點(diǎn)與 weak 的區(qū)別
  • copy 此特質(zhì)所表達(dá)的所屬關(guān)系與 strong 類似,然而設(shè)置方法并不保留新值,而是將其拷貝,多用于 NSString.
7. 在對象內(nèi)部盡量直接訪問實例變量

直接訪問實例變量的速度比較快,因為不經(jīng)過 Objective-C 方法派發(fā),編譯器所生成的代碼會直接訪問保存催下實例量的那塊內(nèi)存.
直接訪問實例變量時,不會調(diào)用設(shè)置方法,這就繞過了相關(guān)屬性所定義的內(nèi)存管理語義.

8. 理解"對象等同性”這一概念

根據(jù)等同性來比較對象是一個非常有用的功能,不過,按照==操作符比較出來的結(jié)果未必是我們想要的,因為該操作比較的事兩個指針本身,而不是其所指的對象.應(yīng)該使用 NSObject 協(xié)議中的聲明的”isEqual”方法來判斷兩個對象的等同性,一般來說兩個類型不同的對象總是不相等的.直接比較字符串的時候 isEqual 比 isEqualToString慢,因為前者還要執(zhí)行額外步驟.

9. 以"類族模式"隱藏實現(xiàn)細(xì)節(jié)

“類族”是一種很用用的模式,可以隱藏抽象基類背后實現(xiàn)的細(xì)節(jié). 這是一種”工廠模式”.比如iOS 用戶界面框架 UIKit 中就有一個名為 UIButton 的類.想創(chuàng)建按鈕,需要調(diào)用下面這個類方法.
+(UIButton*)buttonWithType:(UIButtonType)type;
我到是認(rèn)為,作者想告訴我我們要好好封裝代碼,這個地方?jīng)]啥好說的.

10. 在既有類中使用關(guān)聯(lián)對象存放自定義數(shù)據(jù)

有時需要在對象中存放相關(guān)信息,這是我們通常會從對象所屬的類中繼承一個子類,然后改用這個子類對象.然而并非所有情況下都這么做,有時候類的實例可能是由某種機(jī)制所創(chuàng)建的,而開發(fā)者無法令這種機(jī)制創(chuàng)建出自己所寫的實例. Objective-C 中有意向強(qiáng)大的特性可以解決問題,這就是關(guān)聯(lián)對象.

11. 理解objc_msgSend的作用

用Objetive-C的術(shù)語來說贺嫂,這叫做“消息傳遞”曲饱。這里說的是運(yùn)行時。

12. 理解消息轉(zhuǎn)發(fā)機(jī)制

當(dāng)對象接收到無法解讀的消息后,就會啟動消息轉(zhuǎn)發(fā)機(jī)制氛谜,程序員可經(jīng)此過程告訴對象應(yīng)該圖和處理未知消息杨何。這里說的是運(yùn)行時垃帅。

13. 用方法調(diào)配技術(shù)調(diào)試黑盒方法

運(yùn)行期間订讼,可以向類中新增或替換選擇子所對應(yīng)的方法實現(xiàn)定踱。
使用另一份實現(xiàn)來替換原有的方法實現(xiàn),這道工序叫做方法調(diào)配,開發(fā)者常用此技術(shù)想原有實現(xiàn)中添加新功能粤剧。
一般來說株憾,只有調(diào)試程序的時候才需要運(yùn)行期修改方法實現(xiàn),這種做法不易濫用郑藏。這里說的是運(yùn)行時擦耀。

14. 理解類對象的用意

每個Objective-C對象實例都是指向某塊內(nèi)存數(shù)據(jù)的指針汽纤,如果把對象所需的內(nèi)存分配到棧上編譯器就會報錯
每個對象結(jié)構(gòu)體的首個成員是Class類的變量,該變量定義了對象所屬的類瞳购,通常稱為isa指針碴萧。

typedef struct objc_class *class
struct objc_class{
    Class isa;
    Class super_class;
    const char* name;
    long version;
    long info;
    long instance_size;
    struct objc_ivar_list *ivars;
    struct objc_method_list *ivars;
    struct objc_cache *cache;
    struct objc_protocol_list protocols;
}

此結(jié)構(gòu)體存放類的元數(shù)據(jù),例如類的實例實現(xiàn)了幾個方法履磨,具備多少個實例變量等信息刽宪。次結(jié)構(gòu)體的首個變量也是isa指針厘贼,這說明Class本身亦為Objctive-C對象。結(jié)構(gòu)體里還有個變量叫做super_class,它定義本類的超類圣拄,類對象所屬的類型(isa指針?biāo)赶虻念愋停┦橇硗庖粋€類,叫做元類,用來標(biāo)書類本身所具備的元數(shù)據(jù)则果。類方法就定義于此處棠赛,因為這些方法可以理解成類對象的實例方法,每個類僅有一個類對象饭耳,每個類對象僅有一個與之相關(guān)的元類串述。 (元數(shù)據(jù),就是這個類的數(shù)據(jù)哥攘。)
isKindOfClass:能夠判斷對象是否為某類或其派生類的實例
isMemberOfClass: 能夠判斷出對象是否為某個特定類的實例

15. 用前綴避免命名空間沖突

這個沒啥可說的

16. 提供全能初始化方法

這個沒啥可說的

17. 實現(xiàn)description方法

調(diào)試程序時經(jīng)常需要打印并查看對象信息剖煌。description 很實用。

Person.h
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property(nonatomic,assign)int age;
@property(nonatomic ,copy)NSString* name;
@end

Person.m
#import "Person.h"
@implementation Person
- (NSString *)description
{
    return [NSString stringWithFormat:@"name %@ , age %d", self.name, self.age];
}
@end

description寫出想要的屬性逝淹, 在ViewController打印 Person 對象 Person的相關(guān)屬性就會出現(xiàn)在控制臺耕姊。

18. 盡量使用不可變對象

這個沒啥可說的

19. 使用清晰而協(xié)調(diào)的全名方式

這個沒啥可說的

20. 為私有方法名加前綴

這個沒啥可說的

21. 理解Objective-C錯誤模型

NSError的用法更加靈活,因此經(jīng)由此對象栅葡,我們可以把導(dǎo)致錯誤的原因匯報給調(diào)用者茉兰。

  • NSError domain(錯誤范圍,其類型為字符串)
    錯誤發(fā)生的范圍欣簇,也就是產(chǎn)生錯誤的根源规脸,通常用一個特有的全局變量來定義,比方說 “處理URL子系統(tǒng)”從URL的解析獲取數(shù)據(jù)時如果出錯了熊咽,那么就會使用NSURLErrorDomain來表示錯誤范圍
  • Error code(錯誤碼莫鸭,其類型為整數(shù))
    獨(dú)有的錯誤代碼,用以指明在某個范圍內(nèi)具體發(fā)生了何種錯誤横殴。某個特性范圍內(nèi)可能會發(fā)生一系列相關(guān)錯誤被因,這些錯誤情況通常采用enum來定義。例如,當(dāng)HTTP請求出錯時梨与,可能會把HTTP狀態(tài)碼設(shè)為錯誤碼
  • User info(用戶信息堕花,其類型為字典)
    有關(guān)錯誤的額外信息,其中或許包含一段“本地化的描述”或許還含有導(dǎo)致錯誤發(fā)生的另外一個錯誤粥鞋,經(jīng)由此種信息缘挽,可將相關(guān)錯誤串成一條“錯誤鏈”
@try {
        NSString *str = @"wotaxiwa";
        NSString *strErr = [str substringFromIndex:100];
        NSLog(@"%@",str);
    } @catch (NSException *exception) {
       
        NSLog(@"ERROR:     %@",exception);
    } @finally {
        NSLog(@"%s",__func__);
    }

如果出現(xiàn)exception,異常后面的代碼將不會繼續(xù)執(zhí)行

22. 理解NSCopying協(xié)議
  • copy方法實際上是調(diào)用 -(id)copyWithZone:(NSZone*)zone; 實現(xiàn)copy操作呻粹, 如果想對自己的類支持拷貝并且做額外操作壕曼,那就要實現(xiàn)NSCopying協(xié)議此的方法。
    為何出現(xiàn)NSZone呢尚猿,以前開發(fā)程序時窝稿,會據(jù)此把內(nèi)存分成不用的區(qū),而對象會創(chuàng)建在某個區(qū)凿掂。 現(xiàn)在不用了伴榔,每個程序只有一個區(qū):“默認(rèn)區(qū)”,所以不用擔(dān)心zone參數(shù)庄萎。
    copy方法由NSObject實現(xiàn)踪少,該方法只是以默認(rèn)區(qū)為參數(shù)調(diào)用。

  • mutableCopy方法實際上是調(diào)用 -(id)mutableCopyWithZone:(NSZone*)zone; 實現(xiàn)mutableCopy操作

copy mutableCopy 我認(rèn)為就是原型設(shè)計模式不明白的同學(xué)請看這個網(wǎng)頁

涉及到深拷貝和淺拷貝的知識不明白的同學(xué)請看這篇博客

23. 通過委托與數(shù)據(jù)協(xié)議進(jìn)行對象間通信

這一條說的就是delegate(代理設(shè)計模式)糠涛。但是并沒有說delegate的循環(huán)引用的問題,在使用代理聲明一個 @property的時候援奢,記得用weak。

@protocol PersonDelegate <NSObject>
-(void)areYouPerson;
@end

@property (nonatomic,weak)id<PersonDelegate> pd;
24. 將類的實現(xiàn)代碼分散到便于管理的數(shù)個分類之中

這個沒啥可說的

25. 總是為第三方類的分類名稱加前綴

這個沒啥可說的

26. 勿在分類中聲明屬性

正常的分類是不可以聲明屬性的忍捡,但是從技術(shù)上說集漾,分類里可以用runtime聲明屬性。

#import <objc.runtime.h>
static const char *kFriendsPropertyKey = “kFriendsPropertyKey”;
@implementation EOCPerson(Friendship)
-(NSArray*)friends{
    return objc_getAssociatedObject(self,kFriendsPropertyKey);
}

-(void)setFriends:(NSArray*)friends{
    objc_setAssociateObject(self.kFriendsPropertyKey,friends,OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end

這樣做可行砸脊,但是不太理想具篇,要吧相似的代碼寫很多遍。而且容易出現(xiàn)Bug凌埂,可以使用class-continuation實現(xiàn)分類添加屬性驱显。

27. 使用class-continuation分類隱藏實現(xiàn)細(xì)節(jié)

class-continuation分類和普通的分類不同,它必須在其所接續(xù)的那個類的實現(xiàn)文件里瞳抓。其重要之處在于埃疫,這是唯一能生命實例變量的分類,而且此分類沒有特定的實現(xiàn)文件孩哑,其中的方法應(yīng)該定義在類的主實現(xiàn)文件里栓霜。與其他分類不用,“class-continuation分類”沒有名字横蜒,比如叙淌,有個類叫做EOCPerson秤掌,其“class-continuation分類”寫法如下:

@interface EOCPerson()
@end

我們在創(chuàng)建一個類的時候系統(tǒng)已經(jīng)自動幫我們在,m中實現(xiàn)了愁铺,以下代碼都應(yīng)該很熟悉吧鹰霍。

#import "ViewController.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
  
}
@end

沒錯它就是 class-continuation分類,在此代碼之間可以添加屬性茵乱,修改屬性茂洒。

@interface ViewController ()
@end

使用class-continuation分類的好處

  • 可以向類中新增實例變量。
  • 如果類中的主接口聲明為只讀瓶竭,可以再類內(nèi)部修改此屬性督勺。
  • 把私有方法的原型文件生命在”class-continuation分類”里面。
  • 想使類遵循的協(xié)議不為人知斤贰,可以用“class-continuation分類”中聲明智哀。
28. 通過協(xié)議提供匿名對象

這個沒啥可說的
說的就是這句話

@property (nonatomic,weak)id<PersonDelegate> pd;
29. 理解引用計數(shù)

理解引用計數(shù),方便于了解iOS的內(nèi)存管理荧恍。不過現(xiàn)在都是ARC的時代了瓷叫。
引用計數(shù)機(jī)制通過可以遞增遞減的計數(shù)器來管理內(nèi)存。對象創(chuàng)建好之后送巡,其保留計數(shù)至少為1摹菠。若保留計數(shù)為正,則對象繼續(xù)存活骗爆。當(dāng)保存計數(shù)降為0次氨,對象就被銷毀了。
在對象生命期中摘投,其余對象通過引用來保留或釋放此對象煮寡。保留與釋放操作分別會遞增及遞減保留計數(shù)。

30. 以ARC簡化引用計數(shù)

使用ARC要計數(shù)犀呼,引用計數(shù)實際上還是要執(zhí)行的幸撕,只不過保留與釋放操作現(xiàn)在由ARC自動為你添加。由于ARC會自動執(zhí)行retain圆凰、release杈帐、autorelease等操作,所以直接在ARC下調(diào)用這些內(nèi)存管理方法是非法的专钉。
ARC在調(diào)用這些方法時挑童,并不用過普通的Objective-C消息派發(fā)機(jī)制,二十直接調(diào)用其底層C語言版本跃须,這樣做性能更好站叼,直接調(diào)用底層函數(shù)節(jié)省很多CPU周期。
雖然有了ARC之后無需擔(dān)心內(nèi)存管理問題菇民,但是CoreFoundation對象不歸ARC管理尽楔,開發(fā)者必須適時調(diào)用CFRetain/CFRelease.

31. 在dealloc方法中只釋放引用并解除監(jiān)聽

當(dāng)一個對象銷毀的時候會調(diào)用dealloc方法投储,但是當(dāng)開銷較大或系統(tǒng)內(nèi)稀缺資源則不再此列,像是文件描述阔馋、套接字玛荞、大塊內(nèi)存等都屬于這種資源,通常對于開銷較大的資源實現(xiàn)一個方法呕寝,當(dāng)程序用完資源對象后勋眯,就調(diào)用此方法。這樣一來下梢,資源對象的生命期就變得明確了客蹋。

32.編寫“異常安全代碼”時留意內(nèi)存管理問題

圖不重要看字。
圖片中的情景是MRC∧踅現(xiàn)在已經(jīng)是ARC時代了讶坯。但是在使用@try 的時候也要注意,在捕獲到異常的時候@try{}中的語句執(zhí)行到異常代碼的那一行后不在執(zhí)行岗屏,然后把異常拋給@catch辆琅。當(dāng)然@finally是一定要執(zhí)行的。
如下 并沒有執(zhí)行代碼中的NSLog(@"%@",array);

    @try {
        NSArray *array = @[@"a",@"b",@"c"];
        NSString *str_arr = array[4];
        NSLog(@"%@",array);

    } @catch (NSException *exception) {
        NSLog(@"%@",exception);
    } @finally {
        NSLog(@"%s",__func__);
    }
33. 以弱引用避免保留環(huán)
  • unsafe_unretained 語義同assign等價担汤。然而assign通常用于int涎跨、float、結(jié)構(gòu)體等崭歧。unsafe_unretained多用于對象類型隅很。
  • weak 與 unsafe_unretained 作用相同,然而只要系統(tǒng)把屬性回收率碾,屬性值為nil叔营。
    推薦使用weak,畢竟是ARC時代的產(chǎn)物所宰,而且用的人也很多绒尊。
34. 以“自動釋放池塊”降低內(nèi)存峰值
    @autoreleasepool {
        <#statements#>
    }

    for (int i = 0; i < 1000000; i++) {
        @autoreleasepool {
            NSNumber *num = [NSNumber numberWithInt:i];
            NSString *str = [NSString stringWithFormat:@"%d ", i];
            [NSString stringWithFormat:@"%@%@", num, str];
           
            if(lagerNum-1 == i)
            {
                NSLog(@"end");
            }
        }
    }


由此可見我們合理運(yùn)用自動釋放池,可降低應(yīng)用程序的內(nèi)存峰值仔粥。

35. 用“僵尸對象"調(diào)試內(nèi)存管理問題

向已回收的對象發(fā)送消息是不安全的婴谱。
在左上角標(biāo)題欄找到項目單擊后選擇 Edit scheme 勾選圖中檢測僵尸對象


36. 不要使用retainCount

這個沒啥可說的
MRC時代的產(chǎn)物,忽略

37. 理解”塊“這一概念

這里其實就是在說block躯泰,復(fù)習(xí)一下block的語法吧
返回值類型(block名稱)(參數(shù))
需要注意的是 定義block時候谭羔,其所占內(nèi)存區(qū)域是分配在棧中的,快只在定義它的那個范圍內(nèi)有效麦向。block所使用的整個內(nèi)存區(qū)域瘟裸,在編譯期已經(jīng)完全確定,因此诵竭,全局block可以生命在全局內(nèi)存里话告,而不需要在每次用到的時候于棧中創(chuàng)建兼搏,另外,全局block的拷貝是個空操作沙郭,因為全局block絕不可能為系統(tǒng)所回收佛呻,這種block實際上相當(dāng)于單例。

38. 為常用的塊類型創(chuàng)建typedef

這個沒啥可說的

typedef <#returnType#>(^<#name#>)(<#arguments#>);
@property (nonatomic,copy)name nm_blk;
39. 用handler塊降低代碼分散程度

這條書上說的就是block的回調(diào)棠绘。只不過是把block放在方法中去使用件相。

//  Person.h
#import <Foundation/Foundation.h>
typedef void(^Blk)(NSString *name,int age);
@interface Person : NSObject
-(void)handler:(Blk)blk;
@end

//  Person.m
#import "Person.h
@implementation Person
-(void)handler:(Blk)blk{
    if(blk){
        blk(@"zhangsan" ,28);
    }
}
@end

//  使用
Person *per =[Person new];
[per handler:^(NSString *name, int age) {
     NSLog(@"%@ %d",name, age);
}];

這樣使用的好處是 在兩個對象通信的時候可以不使用delegate,方便了代碼的管理氧苍。其實這樣的用法很常見,多用于封裝網(wǎng)絡(luò)請求的基類泛范。

40. 用塊引用其所屬對象時不要出現(xiàn)保留環(huán)

這個沒啥可說的

41. 多用派發(fā)隊列让虐,少用同步鎖

派發(fā)隊列可用來表述同步語義,這種做法比使用@synchronize塊或NSLock對象更簡單
將同步與異步派發(fā)結(jié)合起來罢荡,可以實現(xiàn)與普通枷鎖機(jī)制一樣的同步行為赡突,而這么做卻不會阻塞執(zhí)行異步派發(fā)的線程
使用同步隊列及柵欄塊,可以令同步行為更加高效(不常用)

42. 多用GCD区赵,少用performSelector系列方法

這個沒啥可說的

43. 掌握GCD及操作隊列的適用時機(jī)

這個沒啥可說的
解決多線程與任務(wù)管理問題時惭缰,派發(fā)隊列并非唯一方案
操作隊列提供了一套高層的Objective-C API 能實現(xiàn)純GCD所具備的絕大部分功能,而且還完成一些更為復(fù)雜的操作笼才,那些操作弱改用GCD來實現(xiàn)漱受,則需另外編寫代碼。
使用NSOperation對線程管理

44. 通過Dispatch Group機(jī)制骡送,根據(jù)系統(tǒng)資源狀況來執(zhí)行任務(wù)

這個沒啥可說的
一系列任務(wù)可歸入一個dispatch group之中昂羡。開發(fā)者可以在這組任務(wù)執(zhí)行完畢時獲得通知
通過dispatch group,可以在并發(fā)式派發(fā)隊列里同時執(zhí)行多項任務(wù)摔踱。此時GCD會根據(jù)系統(tǒng)西苑狀況來調(diào)度這些并發(fā)執(zhí)行的任務(wù)虐先。開發(fā)者若自己來實現(xiàn)此功能。則需要便攜大量代碼派敷。

45. 使用dispatch_once來執(zhí)行秩序運(yùn)行一次的線程安全代碼
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
        <#code to be executed once#>
});
46.不用使用dispatch_get_current_queue

這個沒啥可說的
iOS系統(tǒng)6.0版本起蛹批,已經(jīng)正式啟用此函數(shù)了

__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_6,__MAC_10_9,__IPHONE_4_0,__IPHONE_6_0)
DISPATCH_EXPORT DISPATCH_PURE DISPATCH_WARN_RESULT DISPATCH_NOTHROW
dispatch_queue_t
dispatch_get_current_queue(void);


47.熟悉系統(tǒng)框架

打開Xcode command + shift + 0 選擇性的了解一些 Foundation、UIKit
也可以看看這篇博客 http://www.reibang.com/p/58bc11c800e4

48. 多用枚舉篮愉,少用for循環(huán)

因為枚舉遍歷的時候用的多線程(GCD并發(fā)執(zhí)行)腐芍,所以效率更快些。我覺得其實用什么都行潜支。

NSArray *arr = @[@"b",@"c",@"s"];
[arr enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
 }];
49. 對自定義其內(nèi)存管理語義的collection使用無縫橋接
NSArray *anNSArray = @[@1,@3,@5,@8];
CFArrayRef acFArray =  (__bridge CFArrayRef)anNSArray;
NSLog(@"%@",acFArray);

通過無縫橋接技術(shù)甸赃,可以在Foundation框架中Objective-C對象與CoreFoundation框架中的C語言數(shù)據(jù)結(jié)構(gòu)之間來回轉(zhuǎn)換。
在CoreFoundation層面穿件collection時冗酿,可以指定許多回調(diào)函數(shù)埠对,這些函數(shù)表示此collection應(yīng)如何處理其元素络断,然后可運(yùn)用無縫橋接技術(shù),將其轉(zhuǎn)換成具備特殊內(nèi)存管理語義的Objective-C collection项玛。

50. 構(gòu)建緩存時選用NSCache而非NSDictionary

NSCache勝過NSDictionary之處在于貌笨,當(dāng)系統(tǒng)資源耗盡時,它能自動刪減緩存襟沮。

51. 精簡Initialize與load的實現(xiàn)代碼

類初始化的時候一定會調(diào)用兩個方法

+(void)load{}

+ (void)initialize
{
    if (self == [<#ClassName#> class]) {
        <#statements#>
    }
}
  • load方法只會調(diào)用一次锥惋,不管該類的頭文件有沒有被使用,該類都會被系統(tǒng)自動調(diào)用开伏,而且只調(diào)用一次膀跌。 當(dāng)然了,如果不重寫這個方法的話固灵,我們是不知道這個方法有沒有被調(diào)用的捅伤。
    如果分類也重寫了load方法,先調(diào)用類里的巫玻,在調(diào)用分類丛忆。

  • initialize 和load類似,不過在類被初始化的時候才會被調(diào)用(init之前)仍秤。需要注意的是熄诡,<#ClassName#>如果有子類繼承的時候要判斷類名。

52. 別忘了NSTimer會保留其目標(biāo)對象
//  Person.h
#import <Foundation/Foundation.h>

@interface Person : NSObject
@property (nonatomic,strong)NSTimer *timer;
-(void)start;
-(void)stop;
@end

//  Person.m
#import "Person.h"
@implementation Person

-(void)start{
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(run) userInfo:nil repeats:YES];
}

-(void)run{
    NSLog(@"%s",__func__);
}

-(void)dealloc{
    NSLog(@"%s",__func__);
}

-(void)stop{
    [self.timer invalidate];
}
@end


調(diào)用
@property (nonatomic,strong)Person *person;

self.person = [Person new];
[self.person start];


-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    [self.person stop];
}

好诗力,那么問題來了凰浮,是不是沒有調(diào)用dealloc方法,沒有調(diào)用dealloc方法就說明Person對象并沒有被銷毀姜骡,為什么沒有被銷毀

因為在控制器強(qiáng)引用了self.person导坟,[self.person start]強(qiáng)引用了 self.timer; self.timer 的target指向了self(self.person)所以循環(huán)引用了。


怎么解決圈澈。 NSTimer銷毀的時候惫周,把Person對象為nil即可

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    [self.person stop];
    self.person = nil;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市康栈,隨后出現(xiàn)的幾起案子递递,更是在濱河造成了極大的恐慌,老刑警劉巖啥么,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件登舞,死亡現(xiàn)場離奇詭異,居然都是意外死亡悬荣,警方通過查閱死者的電腦和手機(jī)菠秒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來氯迂,“玉大人践叠,你說我怎么就攤上這事言缤。” “怎么了禁灼?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵管挟,是天一觀的道長。 經(jīng)常有香客問我弄捕,道長僻孝,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任守谓,我火速辦了婚禮穿铆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘分飞。我一直安慰自己悴务,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布譬猫。 她就那樣靜靜地躺著,像睡著了一般羡疗。 火紅的嫁衣襯著肌膚如雪染服。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天叨恨,我揣著相機(jī)與錄音柳刮,去河邊找鬼。 笑死痒钝,一個胖子當(dāng)著我的面吹牛秉颗,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播送矩,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼蚕甥,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了栋荸?” 一聲冷哼從身側(cè)響起菇怀,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎晌块,沒想到半個月后爱沟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡匆背,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年呼伸,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片钝尸。...
    茶點(diǎn)故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡括享,死狀恐怖搂根,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情奶浦,我是刑警寧澤兄墅,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站澳叉,受9級特大地震影響隙咸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜成洗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一五督、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧瓶殃,春花似錦充包、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至冠场,卻和暖如春家浇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背碴裙。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工钢悲, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人舔株。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓莺琳,卻偏偏與公主長得像,于是被迫代替她去往敵國和親载慈。 傳聞我的和親對象是個殘疾皇子惭等,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評論 2 345

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