轉(zhuǎn)載請注明出處:http://www.olinone.com/
ReactNative是Facebook開源的一種實現(xiàn)移動跨平臺開發(fā)的解決方案逝段,目前在業(yè)界得到廣泛應(yīng)用私股,這里有非常詳細的中文使用指南刷允。本文主要分享RN源碼中一些值得大家學(xué)習(xí)或者借鑒的代碼或者編寫技巧等冤留,供大家學(xué)習(xí)參考
整個RN庫包含10多個工程,有興趣的童鞋可以下載源碼查看具體細節(jié)树灶,在此不再展開
宏定義巧用
整個ReactNative源碼工程中用到了大量的宏定義纤怒,包括RCT_EXTERN、RCT_NOT_IMPLEMENTED破托、RCT_EXPORT_METHOD以及RCT_EXPORT_MODULE等申明宏或者功能宏肪跋。通過宏定義的方式,可以非常方便嵌入功能代碼或者邏輯實現(xiàn)土砂,重用代碼的同時又保持了代碼的整潔性
比如州既,ProtocolKit工程中谜洽,作者通過宏定義@defs將Protocol接口巧妙的實現(xiàn)在.h文件中,代碼簡介明了吴叶,又不失功能完整性阐虚。當(dāng)然,RN工程中蚌卤,RCT_NOT_IMPLEMENTED宏也有相似作用实束,實際項目中各位也可以嘗試通過宏定義實現(xiàn)一些常用功能模塊
關(guān)于iOS宏定義的文章有很多,在此推薦兩篇非常不錯的文章:RAC中必須要知道的宏逊彭、ios宏的使用和技巧
環(huán)境變量
iOS開發(fā)中咸灿,各位對#ifdef DEBUG應(yīng)該非常熟悉,通過判斷該條件侮叮,可以區(qū)別當(dāng)前運行環(huán)境是Debug環(huán)境還是Release環(huán)境避矢。比如Release環(huán)境下通過重定義NSLog以屏蔽所有日志輸出
#ifdef DEBUG
#define NSLog(...) NSLog(__VA_ARGS__)
#else
#define NSLog(...) {}
#endif
進一步,是否可以考慮只在聯(lián)機調(diào)試環(huán)境下輸出日志囊榜?此時就涉及聯(lián)機調(diào)試環(huán)境的判斷审胸,環(huán)境變量正好可以解決該問題
Xcode可以在不同環(huán)境下自定義環(huán)境變量Environment Variables,通過在運行環(huán)境Run中自定義變量CI_USE_PACKAGER卸勺,此時便可在項目代碼中通過getenv()函數(shù)判斷當(dāng)前運行環(huán)境
if (getenv("CI_USE_PACKAGER")) {
? ? // to do...
}
被忽略的硬鍵盤
相較于軟鍵盤文字符號的輸入砂沛,對于APP來說,硬鍵盤的應(yīng)用開發(fā)似乎很容易被忽視曙求,畢竟碍庵,通常情況下,硬鍵盤輸入只會出現(xiàn)在模擬器環(huán)境下
iOS7以后圆到,系統(tǒng)定義有硬鍵盤響應(yīng)交互類UIKeyCommand怎抛,通過UIKeyCommand,APP能夠監(jiān)聽硬鍵盤的特定輸入響應(yīng)芽淡,比如Command+D等马绝,當(dāng)然,前提是APP需要首先監(jiān)聽該輸入命令
UIKeyCommand的使用非常簡單挣菲,當(dāng)需要在特定場景觸發(fā)某一事件富稻,但又不想影響界面顯示的時候,不妨試試UIKeyCommand白胀,具體使用可以看看這篇文章
_cmd
iOS官方文檔中椭赋,_cmd表示當(dāng)前方法的selector,你可以通過下面代碼打印輸出當(dāng)前函數(shù)名
NSLog(@"Current method: %@", NSStringFromSelector(_cmd));
當(dāng)然或杠,實際項目中哪怔,你也可以這樣使用
NSNumber *rootTag = objc_getAssociatedObject(self, _cmd) ?: @1;
objc_setAssociatedObject(self, _cmd, @(rootTag.integerValue + 10), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
瞧,是不是有點意思!
kCFNull
相對于nil NSNull而言认境,kCFNull筆者接觸較少胚委,kCFNull可以理解為NSNull單例對象
id null1 = (id)kCFNull;
id null2 = [NSNull null];
打印地址
null1=(NSNull *)0x10426eaf0
null2=(NSNull *)0x10426eaf0
從上面測試結(jié)果可以看出它們其實指向同一地址, 可以簡單理解為 kCFNull === [NSNull null]
文本陰影NSShadow
APP開發(fā)中叉信,程序猿可能經(jīng)常需要在圖片或視頻上顯示文字亩冬,由于背景顏色跟文字顏色相近,導(dǎo)致文字看不清硼身,比如時下火熱的直播彈幕顯示硅急,為了確保文字顯示清晰,開發(fā)者一般會配上陰影或者文字描邊
給文本添加陰影描邊佳遂,系統(tǒng)提供有NSShadow類营袜,可以這樣使用
NSShadow *shadow = [NSShadow new];
shadow.shadowOffset = CGSizeZero;
shadow.shadowBlurRadius = 5.0f;
shadow.shadowColor = [UIColor colorWithWhite:0.0f alpha:0.3f];
NSAttributedString *attString = [[NSAttributedString alloc] initWithString:@"www.olinone.com" attributes:@{NSShadowAttributeName: shadow, NSForegroundColorAttributeName: [UIColor whiteColor]}];
lbl.attributedText = attString;
實際效果是這樣的,shadowBlurRadius值越小讶迁,文本描邊越清晰
主線程判斷
判斷當(dāng)前執(zhí)行線程是否為主線程的方法有很多连茧,比如
[NSThread isMainThread]
pthread_main_np
在RN中,它是這樣的
BOOL RCTIsMainQueue() {
? ? ? static void *mainQueueKey = &mainQueueKey;
? ? ? static dispatch_once_t onceToken;
? ? ? dispatch_once(&onceToken, ^{
? ? ? ? ? dispatch_queue_set_specific(dispatch_get_main_queue(), mainQueueKey, mainQueueKey, NULL);
? });
? ? ? return dispatch_get_specific(mainQueueKey) == mainQueueKey;
}
當(dāng)然巍糯,由于無法查看NSThread內(nèi)部實現(xiàn)機制,暫時無法了解孰優(yōu)孰劣客扎,不過祟峦,[NSThread isMainThread]貌似足矣!
volatile不簡單
在百科中徙鱼,是這樣描述它的:就像大家更熟悉的const一樣宅楞,volatile是一個類型修飾符,它是被設(shè)計用來修飾被不同線程訪問和修改的變量袱吆。作為指令關(guān)鍵字厌衙,確保本條指令不會因編譯器的優(yōu)化而省略,且要求每次直接讀值
簡單說绞绒,被volatile修飾的變量是多線程安全的婶希,其次,不會因為編譯器優(yōu)化導(dǎo)致讀值出錯蓬衡。關(guān)于編譯器編譯優(yōu)化可以看看這篇文章
iOS開發(fā)中確保多線程安全的方法有很多喻杈,原子操作、線程鎖狰晚、單線程執(zhí)行等等筒饰,本人也寫過相關(guān)文章iOS開發(fā)多線程同步
在RN中,通過volatile修飾符壁晒,巧妙實現(xiàn)了多線程取消操作
__block volatile uint32_t cancelled = 0;
if (!cancelled) {
? ? // to do...
}
OSAtomicOr32Barrier(1, &cancelled);
通過原子性操作訪問被volatile修飾的cancelled對象即可保障函數(shù)只執(zhí)行一次瓷们。想想大家熟悉的單例dispatch_once_t,現(xiàn)在讓你設(shè)計單例對象,你又會如何設(shè)計了谬晕?
+ (instancetype)sharedInstance {
? ? static RCTWebSocketManager *sharedInstance = nil;
? ? static dispatch_once_t onceToken;
? ? dispatch_once(&onceToken, ^{
? ? ? ? sharedInstance = [self new];
? ? });
? ? return sharedInstance;
}
結(jié)構(gòu)體Struct
說起Struct式镐,不知各位對它印象如何?大學(xué)C課本中學(xué)過固蚤?NSObject類class原型貌似有講娘汞?
struct iOSDev {
? ? NSString *nickName;
};
OC中一個簡單的結(jié)構(gòu)體,在Swift中夕玩,Struct也可以這樣寫
struct iOSDev {
? ? var nickName : String
? ? func getBusinessCard() -> String {
? ? ? ? return "\(nickName)你弦,幽默的iOS開發(fā)者!"
? ? }
};
let iOSOlinone = iOSDev(nickName: "olinone")
print(iOSOlinone.getBusinessCard())
getBusinessCard為結(jié)構(gòu)體函數(shù)燎孟,是不是感覺很方便禽作!其實OC中也可以這樣寫
struct iOSDev {
? ? NSString *nickName;
? ? NSString *getBusinessCard() {
? ? ? ? return [NSString stringWithFormat:@"%@,幽默的iOS開發(fā)者揩页!", nickName];
? ? }
};
iOSDev iosDev = iOSDev{@"olinone"};
NSLog(@"%@", iosDev.getBusinessCard());
當(dāng)然旷偿,為Struct添加函數(shù)并不是C語言特性,而是C++特性爆侣,因此萍程,為了編譯通過,你需要將.m文件修改成.mm文件
Struct有其使用的特殊場景兔仰,相較于Class茫负,合理的使用Struct可以使代碼更加整潔。同時乎赴,為了適應(yīng)Swift中Struct強大特性忍法,可以試著在OC項目中嘗試Struct
最后,給大家來個段子吧:
話說一美女要在兩個男人之間做選擇榕吼,一個年紀大饿序,長的丑,是個千萬富翁羹蚣,另一個年輕原探,帥氣,iOS開發(fā)程序猿度宦。 她對他們說踢匣,我會給你們一人一張紙條,寫著我愿意的那張就是我的選擇戈抄。 富翁打開紙條离唬,看見上面寫著我愿意,于是摟著她划鸽,坐上豪車高興的走了输莺。 年輕的小伙很傷心戚哎,打開紙條看見上面寫著:“等我一個月~” ?^o^
寫在文后:
有些童鞋可能經(jīng)常會問一個問題,感覺自己技術(shù)遇到瓶頸嫂用,如何才能進一步提升自己技術(shù)能力型凳?其實這個問題,本人也是摸石頭過河嘱函,不過有一點可以確定甘畅,那就是保持一顆不斷進取的心吧
新建了一個iOS開發(fā)QQ交流群(首頁右上角入群),歡迎廣大iOS開發(fā)朋友一同交流學(xué)習(xí)往弓。當(dāng)然疏唾,你也可以Follow本人GitHub,或者關(guān)注我的新浪微博函似,感謝你的來訪槐脏,下期再見!