面向YYKit學(xué)習(xí)

1.第一問(wèn):聲明在.m頂部的宏是用來(lái)做什么的?


在瀏覽UIScrollView+YYAdd.m文件時(shí),看見一個(gè)宏定義,好奇它是做什么的?往下看吧。

//問(wèn)題路徑:
YYKit/Base/UIKit/UIScrollView+YYAdd.m

//問(wèn)題代碼
#import "UIScrollView+YYAdd.h"
#import "YYKitMacro.h"

YYSYNTH_DUMMY_CLASS(UIScrollView_YYAdd)

@implementation UIScrollView (YYAdd)
...
@end

YYSYNTH_DUMMY_CLASS這個(gè)宏是做什么的?
點(diǎn)進(jìn)去看看實(shí)現(xiàn):

/**
 Add this macro before each category implementation, so we don't have to use
 -all_load or -force_load to load object files from static libraries that only
 contain categories and no classes.
 More info: http://developer.apple.com/library/mac/#qa/qa2006/qa1490.html .
 *******************************************************************************
 Example:
     YYSYNTH_DUMMY_CLASS(NSString_YYAdd)
 */
#ifndef YYSYNTH_DUMMY_CLASS
#define YYSYNTH_DUMMY_CLASS(_name_) \
@interface YYSYNTH_DUMMY_CLASS_ ## _name_ : NSObject @end \
@implementation YYSYNTH_DUMMY_CLASS_ ## _name_ @end
#endif

在ios開發(fā)過(guò)程中,有時(shí)候會(huì)用到第三方的靜態(tài)庫(kù)(.a文件),OC沒(méi)有為每個(gè)函數(shù)(或者方法)定義鏈接符號(hào),它只為每個(gè)類創(chuàng)建鏈接符號(hào)。這樣當(dāng)在一個(gè)靜態(tài)庫(kù)中使用類別來(lái)擴(kuò)展已有類的時(shí)候,鏈接器不知道如何把類原有的方法和類別中的方法整合起來(lái),就會(huì)導(dǎo)致你調(diào)用類別中的方法時(shí),會(huì)出現(xiàn)selector not recognized的錯(cuò)誤,從而導(dǎo)致app閃退。使用這段宏定義他可以虛擬新建一個(gè)與名字category 相同.h.m 讓編譯器 編譯通過(guò)。即可解決上面的問(wèn)題。

為什么會(huì)閃退?

Objective-C的鏈接器并不會(huì)為每個(gè)方法建立符號(hào)表,而是僅僅為類建立了符號(hào)表。這樣的話,如果靜態(tài)庫(kù)中定義了已存在的一個(gè)類的分類,鏈接器就會(huì)以為這個(gè)類已經(jīng)存在,不會(huì)把分類和核心類的代碼合起來(lái)。這樣的話,在最后的可執(zhí)行文件中,就會(huì)缺少分類里的代碼,這樣函數(shù)調(diào)用就失敗了。
接著仔細(xì)閱讀庫(kù)文件的說(shuō)明文檔,你可能會(huì)在文檔中發(fā)現(xiàn)諸如在Other Linker Flags中加入-ObjC或者-all_load這樣的解決方法。

看完這些解釋,對(duì)這個(gè)宏一知半解,好奇的我又產(chǎn)生了新的問(wèn)題:關(guān)于Xcode的Other Linker Flags
閱讀這篇文章需要了解:鏈接器做什么

另外,在Ohter Linker Flags中的可使用命令行如下:

//加了這個(gè)參數(shù)后,鏈接器就會(huì)把靜態(tài)庫(kù)中所有的Objective-C類和分類都加載到最后的可執(zhí)行文件中。
-ObjC

//會(huì)讓鏈接器把所有找到的目標(biāo)文件都加載到可執(zhí)行文件中,但是千萬(wàn)不要隨便使用這個(gè)參數(shù)!假如你使用了不止一個(gè)靜態(tài)庫(kù)文件,然后又使用了這個(gè)參數(shù),那么你很有可能會(huì)遇到ld: duplicate symbol錯(cuò)誤,因?yàn)椴煌膸?kù)文件里面可能會(huì)有相同的目標(biāo)文件,所以建議在遇到-ObjC失效的情況下使用-force_load參數(shù)。
-all_load

//所做的事情跟-all_load其實(shí)是一樣的,但是-force_load需要指定要進(jìn)行全部加載的庫(kù)文件的路徑,這樣的話,你就只是完全加載了一個(gè)庫(kù)文件,不影響其余庫(kù)文件的按需加載
-force_load

遺留問(wèn)題:
$(inherited)

2.第二問(wèn):聲明在.h的這個(gè)宏是干什么的?


同樣是在瀏覽UIScrollView+YYAdd文件,這回是在.h文件中,看見一個(gè)宏定義,我這好奇心啊。

//問(wèn)題路徑:
YYKit/Base/UIKit/UIScrollView+YYAdd.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN
@interface UIScrollView (YYAdd)
...
@end
NS_ASSUME_NONNULL_END

NS_ASSUME_NONNULL_BEGINNS_ASSUME_NONNULL_END兩個(gè)宏之間的代碼,所有指針對(duì)象都被假定為nonnull, 即不能為空,否則編輯器會(huì)報(bào)警告Null passed to a callee that requires a non-null argument

了解更多:
2015 Objective-C 新特性
Object-C中的黑魔法

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容