OC的消息機制
OC與其他面向?qū)ο笳Z言如C++踱阿、Java的不同之處在于使用消息機制代替方法調(diào)用吓懈。
// OC
NSObject *obj = [NSObject new];
[obj doSomething];
// Java
Object obj = new Object();
obj.doSomething();
兩者關(guān)鍵區(qū)別在于:在使用方法調(diào)用的語言中架忌,程序運行時所應(yīng)執(zhí)行的代碼多數(shù)情況下在編譯時期就已經(jīng)被確定,只有在多態(tài)的情況下才會在運行時查看該調(diào)用哪段代碼。而在OC中,無論是否多態(tài)模闲,程序運行時所應(yīng)執(zhí)行的代碼都是由運行時環(huán)境來決定。所以在OC中崭捍,編譯器并不關(guān)心接收消息的對象是何種類型尸折,所有消息也都在運行時才被處理,也就是OC的動態(tài)綁定機制殷蛇。
@class的使用
如果在一個類SomeClass
的聲明中引用了另一個類OtherClass
实夹,最簡單的做法可能是使用#import "OtherClass.h"
導(dǎo)入這個類,然而這并不是最好的做法粒梦。
假設(shè)SomeClass
又被許多其他類引用亮航,那么每次引用SomeClass
的時候都會同時引用OtherClass
,這會降低一定的編譯性能匀们。更好的做法是在聲明文件中將#import "OtherClass.h"
改為@class OtherClass;
缴淋,在具體使用OtherClass
的文件如SomeClass.m
中,才使用#import "OtherClass.h"
導(dǎo)入這個類泄朴。
// SomeClass.h
#import <Foundation/Foundation.h>
// #import "OtherClass.h"
@class OtherClass;
@interface SomeClass : NSObject
@property (nonatomic) OtherClass * other;
@end
這種做法叫做向前聲明
重抖,向前聲明還可以解決兩個類相互循環(huán)引用的問題。
向前聲明并不是所有情況都適用祖灰,當(dāng)一個類需要繼承自某個父類時仇哆,就必須在聲明中導(dǎo)入父類的頭文件。同樣夫植,當(dāng)一個類需要遵守某個協(xié)議時讹剔,也必須導(dǎo)入?yún)f(xié)議的頭文件。
字面量語法的使用
Foundation框架中的這幾個類NSString详民、NSNumber延欠、NSArray、NSDictionary
都有相應(yīng)的字面量語法沈跨,具體使用如下:
NSString *str = @"some string";
NSNumber *num = @10;
NSArray *arr = @[@"some string", @10];
NSString *someString = arr[0];
NSDictionary *dic = @{@"key1" : @"value1", @"key2" : @"value2"};
NSString *value = dic["key1"];
使用字面量語法不僅可以使代碼簡潔由捎、可讀性強,在數(shù)組和字典的創(chuàng)建過程中饿凛,還有一個小小的優(yōu)點狞玛。
使用字面量語法創(chuàng)建數(shù)組其實本質(zhì)也是調(diào)用NSArray
類的arrayWithObjects:
方法软驰,前面arr數(shù)組的創(chuàng)建等價于如下代碼:
NSArray *arr = [NSArray arrayWithObjects:@"some string", @10, nil];
使用arrayWithObjects:
方法創(chuàng)建數(shù)組時,如果數(shù)組元素中有nil
心肪,會提前結(jié)束方法锭亏,不會拋出異常。這樣會導(dǎo)致數(shù)組元素與邏輯不符硬鞍,卻很難發(fā)現(xiàn)代碼錯誤慧瘤。
而使用字面量語法創(chuàng)建數(shù)組時,如果數(shù)組元素中有nil
固该,則會拋出異常锅减,這樣有利于程序員提前發(fā)現(xiàn)代碼錯誤。
用類型常量代替#define預(yù)處理指令
寫代碼時經(jīng)常遇到需要使用常量的地方伐坏,一般都不推薦直接使用數(shù)字怔匣,因為它既顯得突兀又不利于代碼的維護,通常我們有兩種辦法來定義常量桦沉,一種是使用#define
預(yù)處理命令劫狠,另一種是使用static const
關(guān)鍵字來定義一個常量。
#define ANIMATION_DURATION 0.3
static const NSTimeInterval kAnimationDuration = 0.3
使用#define
預(yù)處理命令僅僅是將代碼中的ANIMATION_DURATION
字符串替換為0.3永部,這樣定義的常量并不具備類型信息独泞,因此無法使用編譯器帶給我們的諸多好處,所以更推薦使用第二種方式定義常量苔埋。
使用static const
關(guān)鍵字來定義常量懦砂,用在類的實現(xiàn)文件中,則此常量只作用在本類中组橄,其他類無法使用荞膘。如果多個類都需使用到某一常量,則需將常量定義成公開的玉工,具體方式是在類的聲明文件中使用extern const
關(guān)鍵字聲明常量羽资,在類的實現(xiàn)文件中使用const
關(guān)鍵字定義常量,這樣任何類只要導(dǎo)入了聲明常量的頭文件就可以直接使用定義好的常量了遵班。
需要注意的是屠升,OC中沒有命名空間的概念,是不允許有多個同名的全局變量存在的狭郑,因此定義公共的常量最好遵守一定的命名規(guī)則腹暖,通常是使用類名作為前綴,如WXGViewAnimationDuration
翰萨。
善用枚舉類型來增強代碼的可讀性
OC的系統(tǒng)框架中脏答,大規(guī)模使用了枚舉類型,蘋果官方也推薦開發(fā)者更多去使用枚舉類型來表達一系列常量。這樣做的好處是使代碼更具可讀性殖告,通過枚舉中每個成員的名字可以很清楚地明白它所代表的意義阿蝶。
可以使用typedef
關(guān)鍵字定義枚舉類型,來省去每次使用枚舉類型時都需要加上enum
關(guān)鍵字的麻煩黄绩。
enum ConnectionState {
ConnectionStateDisconnected,
ConnectionStateConnecting,
ConnectionStateConnected
};
typedef enum ConnectionState ConnectingState;
對于多選枚舉情況羡洁,可以使用按位操作來定義枚舉值,這樣在使用時就可以通過|或&
來控制枚舉的選項宝与。
蘋果官方還定義了兩個宏焚廊,用來快速定義使用自定義變量類型的枚舉冶匹,我們也應(yīng)該更多的使用這兩個宏來定義自己的枚舉习劫。具體使用參考如下代碼:
typedef NS_ENUM(NSInteger, UIViewAnimationTransition) {
UIViewAnimationTransitionNone,
UIViewAnimationTransitionFlipFromLeft,
UIViewAnimationTransitionFlipFromRight,
UIViewAnimationTransitionCurlUp,
UIViewAnimationTransitionCurlDown,
};
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
UIViewAutoresizingNone = 0,
UIViewAutoresizingFlexibleLeftMargin = 1 << 0,
UIViewAutoresizingFlexibleWidth = 1 << 1,
UIViewAutoresizingFlexibleRightMargin = 1 << 2,
UIViewAutoresizingFlexibleTopMargin = 1 << 3,
UIViewAutoresizingFlexibleHeight = 1 << 4,
UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
枚舉類型還經(jīng)常用在switch
分支選擇上,這種情況下最好不要在case
語句中加上default
選項嚼隘,意義在于當(dāng)枚舉中有新成員加入后诽里,因為沒有遍歷所有可能情況,編譯器就會發(fā)出警告飞蛹,從而確保switch
語句能夠正確處理所有情況谤狡。