在 objective-c 中我們可以用@"foo"
來建立乙個nsstring
常量,看起來似乎平淡無奇。
但它背後其實比想象的精彩,@
可以被理解成乙個特殊的巨集,其接受乙個 c 字串作為引數,也可寫作@("foo")
。
之所以說@
是乙個特殊的巨集,是因為其能根據傳入的 c 字串型別不同——c 字串常量或 c 字串——在執行時構建返回不同型別的nsstring
,參見下面的**:
1234567
8
char
*obtain_c_string
(void
)nslog
(@"%@"
,@"foo"
.class
);nslog
(@"%@",@
("bar"
).class
);nslog
(@"%@",@
(obtain_c_string
()).
class
);
輸出結果如下:
123
2013-06
-0501:
14:15.097
sandbox
[45804
:c07
]__nscfconstantstring
2013-06
-0501:
14:15.098
sandbox
[45804
:c07
]__nscfconstantstring
2013-06
-0501:
14:15.098
sandbox
[45804
:c07
]__nscfstring
可見,如果傳入的是 c 字串常量,執行時構建的則為nsconstantstring
;如果傳入的是 c 字串則建立的是nsstring
。
你可能會問這麼理解了又怎樣?
眾所周知,objective-c **裡有很多地方需要我們把**中的一些文法串寫成字串再作為傳入引數,比如 kvo 中的keypath
引數往往就要傳入形如propertya.propertyb
的字串,從實用角度出發這有兩個弊端:
當我們理解了@()
,再加上自定義的巨集,上述兩個問題便可迎刃而解。
1234567
89
/**
* # 將巨集的引數字串化,c 函式 strchr 返回字串中第乙個 '.' 字元的位置
*/#define keypath(keypath) (strchr(#keypath, '.') + 1)
[obja
addobserver
:objb
forkeypath:
@keypath
(obja
.property1
.property2
)// 有**提示,可以被重構掃瞄到
options:
nilcontext:
nil];
這個簡單實現只算是拋磚引玉,除了@()
配合自定義巨集來字串化**中的文法串,更多的用法就有待在開發中不斷發掘了。
ps: 在即將完成這篇文章的時候我發現已有國外開發者利用@()
特性配合自定義巨集,全面系統的解決了上述問題,詳情參見 libextobjc/extkeypathcoding.h。
此外,@()
還可以接受 int 字面量或 int 變數作為引數,有興趣的讀者可以自行感受下。
**:
簡單說說node裡的流
stream 是乙個抽象的介面,node中有很多物件實現了這個介面,例如,對http伺服器發起請求的request物件就是乙個stream,還有process.studo 標準輸出 舉乙個讀取檔案的例子 使用fs.readfilesync同步讀取乙個檔案,程式會被阻塞,所有的資料都會被讀取到記憶體中...
說說TLS協議裡的wireshark抓包內容(一)
我們看到第63號 客戶端向伺服器傳送 client hello 資料報 我們觀察內容 先看到 content type 內容的格式 其實就是說這是握手協議中的 client hello tls中有四種協議 握手協議 22 這裡就是22可以看到 警告協議 21 密碼變更協議 20 這協議沒有出現在我們...
說說TLS協議裡的wireshark抓包內容(二)
第編號70的報文 這是伺服器第一次回給客戶端的第乙個報文 這個報文的內容是server hello 裡面包括了 內容是握手協議 和client hello 一樣 版本是tls v1.2 然後是握手協議的型別 server hello 接著是伺服器生成的隨機數 後面單獨說這個 伺服器生成的會話id 確...