KVC 集合運算符

文章轉(zhuǎn)自http://nshipster.cn/
另外iOS 中集合遍歷方法的比較和技巧 · sunnyxx的技術(shù)博客這篇文章對于KVC 集合運算符的性能也做了描述

Ruby愛好者總愛嘲笑Objective-C臃腫的語法奈搜。

盡管新的Object Literals特性讓我們的語法瘦了幾斤锈遥,但那些紅頭發(fā)的惡霸們還總是用他們的單行map和花哨的Symbol#to_proc來嘲諷我們。

實際上祟印,一門語言是否優(yōu)雅歸結(jié)起來就是其怎么樣能更好的避免循環(huán)篮奄。for库糠,while語句是一種拖累槐臀;即使是快速枚舉也一樣蜡峰。無論你怎么樣使他們看起來更加的友好葡幸,循環(huán)依然是一個在自然語言中用非常簡單方式描述所做事情的代碼塊

"給我這個列表里面所有員工的平均薪酬"最筒,等等。蔚叨。床蜘。

Objective-C

double totalSalary = 0.0;
for (Employee *employee in employees) {
  totalSalary += [employee.salary doubleValue];
}
double averageSalary = totalSalary / [employees count];

╮(╯_╰)╭

幸運的是辙培,鍵-值編碼給我們了一種更加簡潔的,幾乎像Ruby一樣的方式來做這件事:

Objective-C

[employees valueForKeyPath:@"@avg.salary"];

KVC集合運算符允許在valueForKeyPath:方法中使用key path符號在一個集合中執(zhí)行方法邢锯。無論什么時候你在key path中看見了@扬蕊,它都代表了一個特定的集合方法,其結(jié)果可以被返回或者鏈接丹擎,就像其他的key path一樣尾抑。

集合運算符會根據(jù)其返回值的不同分為以下三種類型:

  • 簡單的集合運算符 返回的是strings, number, 或者 dates
  • 對象運算符 返回的是一個數(shù)組
  • 數(shù)組和集合運算符 返回的是一個數(shù)組或者集合

要理解其工作原理,最好方式就是去action里面看看蒂培。想象一個Product類和一個由以下數(shù)據(jù)所組成的products數(shù)組:

Objective-C

@interface Product : NSObject
@property NSString *name;
@property double price;
@property NSDate *launchedOn;
@end

鍵-值 編碼會在必要的時候把基本數(shù)據(jù)類型的數(shù)據(jù)自動裝箱和拆箱到NSNumber或者NSValue中來確保一切工作正常蛮穿。

Name Price Launch Date
iPhone 5 $199 September 21, 2012
iPad Mini $329 November 2, 2012
MacBook Pro $1699 June 11, 2012
iMac $1299 November 2, 2012

簡單集合操作符

  • @count: 返回一個值為集合中對象總數(shù)的NSNumber對象。
  • @sum: 首先把集合中的每個對象都轉(zhuǎn)換為double類型毁渗,然后計算其總践磅,最后返回一個值為這個總和的NSNumber對象。
  • @avg: 把集合中的每個對象都轉(zhuǎn)換為double類型灸异,返回一個值為平均值的NSNumber對象府适。
  • @max: 使用compare:方法來確定最大值。所以為了讓其正常工作肺樟,集合中所有的對象都必須支持和另一個對象的比較檐春。
  • @min: 和@max一樣,但是返回的是集合中的最小值么伯。

例如

Objective-C

[products valueForKeyPath:@"@count"]; // 4
[products valueForKeyPath:@"@sum.price"]; // 3526.00
[products valueForKeyPath:@"@avg.price"]; // 881.50
[products valueForKeyPath:@"@max.price"]; // 1699.00
[products valueForKeyPath:@"@min.launchedOn"]; // June 11, 2012

Pro提示:你可以簡單的通過把self作為操作符后面的key path來獲取一個由NSNumber組成的數(shù)組或者集合的總值疟暖,例如[@[@(1), @(2), @(3)] valueForKeyPath:@"@max.self"] (感謝 @davandermobile, 來自 Objective Sea)

對象操作符

想象下,我們有一個inventory數(shù)組田柔,代表了當(dāng)?shù)靥O果商店的當(dāng)前庫存(iPad Mini不足俐巴,并且沒有新的iMac,因為還沒有發(fā)貨):

Objective-C

NSArray *inventory = @[iPhone5, iPhone5, iPhone5, iPadMini, macBookPro, macBookPro];

  • @unionOfObjects / @distinctUnionOfObjects: 返回一個由操作符右邊的key path所指定的對象屬性組成的數(shù)組硬爆。其中@distinctUnionOfObjects 會對數(shù)組去重, 而且 @unionOfObjects 不會.

例如

Objective-C

[inventory valueForKeyPath:@"@unionOfObjects.name"]; // "iPhone 5", "iPhone 5", "iPhone 5", "iPad Mini", "MacBook Pro", "MacBook Pro"
[inventory valueForKeyPath:@"@distinctUnionOfObjects.name"]; // "iPhone 5", "iPad Mini", "MacBook Pro"

數(shù)組和集合操作符

數(shù)組和集合操作符跟對象操作符很相似欣舵,只不過它是在NSArrayNSSet所組成的集合中工作的。如果我們做一些例如:比較幾個商店中的庫存(和我們上一節(jié)類似的appleStore庫存和買iPhone 5和iPad Mini的versizonStore庫存)這樣的工作缀磕,這個就會很有用缘圈。

  • @distinctUnionOfArrays / @unionOfArrays: 返回了一個數(shù)組,其中包含這個集合中每個數(shù)組對于這個操作符右面指定的key path進行操作之后的值袜蚕。正如你期望的糟把,distinct版本會移除重復(fù)的值。

  • @distinctUnionOfSets: 和@distinctUnionOfArrays差不多, 但是它期望的是一個包含著NSSet對象的NSSet牲剃,并且會返回一個NSSet對象遣疯。因為集合不能包含重復(fù)的值,所以它只有distinct操作颠黎。

例如

Objective-C

[@[appleStoreInventory, verizonStoreInventory] valueForKeyPath:@"@distinctUnionOfArrays.name"]; // "iPhone 5", "iPad Mini", "MacBook Pro"


這可能是一個可怕的想法

令人好奇的是另锋,蘋果的KVC集合操作符文檔冒出了下面這個提示:

注意: 目前還不能自定義集合操作符。

這個提示是有意義的狭归,因為大多數(shù)人在第一次看到集合運算符時都在想這個夭坪。

然而,事實證明过椎,在我們的小伙伴objc/runtime的幫助下室梅,這個實際上 有可以能的實現(xiàn)的。

Guy English有一篇很神奇的文章疚宇,在文章中亡鼠,他swizzles valueForKeyPath:來解析自定義的DSL敷待,其擴展了一些有趣的效果:

Objective-C

NSArray *names = [allEmployees valueForKeyPath: @"[collect].{daysOff<10}.name"];

這段代碼可以得到只有休了不足10天假期的人的名字(無疑是要提醒他們?nèi)バ輦€假吧<浜)

或者,來看個可笑的極端情況:

Objective-C

NSArray *albumCovers = [records valueForKeyPath:@"[collect].{artist like 'Bon Iver'}.<NSUnarchiveFromDataTransformerName>.albumCoverImageData"];

Ruby小伙伴們羨慕吧榜揖。只用一行就在藝人記錄中過濾出來了名字叫"Bon Iver"的藝人勾哩,并且用匹配到的專輯的專輯封面的圖像數(shù)據(jù)初始化了一個NSImage對象。

這是一個好的想法嗎举哟?可能不是思劳。(NSPredicate更加合適,并且其使得邏輯更加簡單妨猩,易懂)

這個很酷嗎潜叛?當(dāng)然啦!這個聰明的例子展示了Objective-C DSL和元編程未來可能的發(fā)展方向壶硅。


KVC集合運算符是一個想節(jié)省幾行代碼并在這一過程中看起來很酷的人必須要了解的威兜。當(dāng)像Ruby這樣的腳本語言自夸它的單行能力是多么的靈活時,我們也許應(yīng)該花一點兒時間來慶祝Objective-C中的約束和集合操作符庐椒。畢竟牡属,Ruby非常非常慢,我說的對嗎扼睬?

作者
Mattt Thompson

Mattt Thompson

Mattt Thompson (@mattt) is the creator & maintainer of AFNetworking and other popular open-source projects, including Postgres.app, ASCIIwwdc and Nomad.

翻譯者

Candyan

Candyan 專業(yè) iOS逮栅,業(yè)余 Android,偶爾搗鼓下Server的工程師窗宇。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末措伐,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子军俊,更是在濱河造成了極大的恐慌侥加,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件粪躬,死亡現(xiàn)場離奇詭異担败,居然都是意外死亡昔穴,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門提前,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吗货,“玉大人,你說我怎么就攤上這事狈网≈姘幔” “怎么了?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵拓哺,是天一觀的道長勇垛。 經(jīng)常有香客問我,道長士鸥,這世上最難降的妖魔是什么闲孤? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮烤礁,結(jié)果婚禮上崭放,老公的妹妹穿的比我還像新娘。我一直安慰自己鸽凶,他們只是感情好币砂,可當(dāng)我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著玻侥,像睡著了一般决摧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上凑兰,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天掌桩,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛暖璧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播则拷,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼曹鸠!你這毒婦竟也來了煌茬?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤彻桃,失蹤者是張志新(化名)和其女友劉穎坛善,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡眠屎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年剔交,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片改衩。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡岖常,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出燎字,到底是詐尸還是另有隱情,我是刑警寧澤阿宅,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布候衍,位于F島的核電站,受9級特大地震影響洒放,放射性物質(zhì)發(fā)生泄漏蛉鹿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一往湿、第九天 我趴在偏房一處隱蔽的房頂上張望妖异。 院中可真熱鬧,春花似錦领追、人聲如沸他膳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽棕孙。三九已至,卻和暖如春些膨,著一層夾襖步出監(jiān)牢的瞬間蟀俊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工订雾, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留肢预,地道東北人。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓洼哎,卻偏偏與公主長得像烫映,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子噩峦,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,614評論 2 353

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

  • KVC集合運算符允許在valueForKeyPath:方法中使用key path符號在一個集合中執(zhí)行方法窑邦。無論什么...
    ping_oO閱讀 505評論 0 0
  • 蘋果官方文檔翻譯 《Objective-C語言編程》(Programming with Objective-C) ...
    fever105閱讀 25,668評論 19 130
  • 展現(xiàn)的全是低俗的交友觀 女生不再潔身自好 男生不再紳士有格 以露骨的話題度過光陰 朋友是擁有各自的圈子 經(jīng)過風(fēng)浪之...
    大情子閱讀 221評論 0 0
  • 最近做畢設(shè)讀論文讀得心累,很多論文公式一堆提升逼格壕探,很多想法也不具普適性冈钦,好像大家都在各玩各的。前兩日看到知乎一個...
    RENO216閱讀 1,846評論 0 1
  • 第一句: 追逐的不是眼前的路李请,而是因為有那么一條路而去追逐 四年前說過這句話瞧筛,那個時候自己還在為高考而作準(zhǔn)備厉熟,那個...
    繼續(xù)海闊天空閱讀 245評論 0 1