KVC之定義集合方法

當你使用這篇文章描述的標準約定創(chuàng)建一個訪問方法和ivar時隆敢,KVC協(xié)議的默認實現(xiàn)可以根據(jù)KVC消息定位它們爽茴。對于表示to-many關(guān)系的集合對象來說也是如此卒稳。但是,如果你實現(xiàn)了集合訪問方法拯啦,我們就可以:

  • 與除了NSArray或NSSet以外的類建立to-many關(guān)系.當我們實現(xiàn)了集合方法,key-value getter的默認實現(xiàn)是返回一個代理對象熔任,該對象調(diào)用這些方法以響應(yīng)后續(xù)收到的NSArrayNSSet消息褒链。屬性對象不必是NSArray或者NSSet,因為代理對象使用集合方法提供預(yù)期的行為疑苔。

  • 改變to-many關(guān)系的內(nèi)容可以提高性能. 協(xié)議的默認實現(xiàn)是使用你的集合方法來改變基礎(chǔ)屬性甫匹,而不是重復創(chuàng)建新的集合對象。

  • 為集合屬性中的內(nèi)容提供KVO訪問 更多內(nèi)容可以查看 Key-Value Observing Programming Guide.

你可以實現(xiàn)兩類集合訪問方法中的一個夯巷,具體取決于我們希望關(guān)系的行為像索引的有序集合(如NSArray對象)還是無序的赛惩、但唯一的集合(如NSSet對象)。任何情況下趁餐,需要至少實現(xiàn)一組方法來支持對屬性的讀取訪問喷兼。

KVC協(xié)議不會聲明在這部分描述的的方法。相反后雷,NSObject提供的協(xié)議的默認實現(xiàn)是在你的KVC兼容對象中查找這些方法季惯,如KVC方法的搜索模式所述,并使用它們來處理部分KVC消息臀突。

訪問有序集合

你可以添加索引訪問方法勉抓,以提供計算、檢索候学、添加和替換有序關(guān)系中的對象的機制藕筋。底層對象通常是NSArrayNSMutableArray對象,但是如果為對象提供了集合訪問方法梳码,我們可以像處理數(shù)組一樣處理這些屬性隐圾。

有序集合的getters

對于沒有默認的getter的集合屬性伍掀。如果你提供以下索引集合方法,則對于valueForKey:消息暇藏,協(xié)議的默認實現(xiàn)是返回一個代理對象蜜笤,其行為類似NSArray,但是會調(diào)用以下集合方法以完成它的工作盐碱。

在現(xiàn)在的OC中把兔,編譯器為每個屬性默認生成了getter,因此默認實現(xiàn)不會創(chuàng)建使用本節(jié)的方法瓮顽∠睾茫可以通過不聲明屬性(僅依靠一個ivar),或者你可以使用@dynamic聲明一個屬性來解決這個問題,這表明我們計劃在運行時提供訪問者行為暖混。無論何種方式,編譯器都不會提供默認的getter聘惦,而默認的實現(xiàn)會使用下面的方法

  • countOf<Key>

    此方法以NSInteger 的形式返回to-many 關(guān)系中對象的個數(shù),就像NSArraycount方法一樣儒恋。事實上善绎,當?shù)讓訉傩允?code>NSArray時,可以使用該方法提供結(jié)果诫尽。

    - (NSUInteger)countOfTransactions {
        return [self.transactions count];
    }
    
  • objectIn<Key>AtIndex: or <key>AtIndexes:

    第一個方法返回 to-many 關(guān)系中指定下標中的對象禀酱,第二個返回一個NSIndexSet參數(shù)指定索引處的對象數(shù)組。 它們分別對應(yīng)于NSArrayobjectAtIndex:objectsAtIndexes:牧嫉。 只需要實現(xiàn)它們中的一個剂跟。transactions數(shù)組的相應(yīng)方法是:

    - (id)objectInTransactionsAtIndex:(NSUInteger)index {
    return [self.transactions objectAtIndex:index];
    }
    
    - (NSArray *)transactionsAtIndexes:(NSIndexSet *)indexes {
    return [self.transactions objectsAtIndexes:indexes];
    }
    
  • get<Key>:range:

    該方法是可選的,但可以提高性能酣藻。它返回集合指定范圍內(nèi)的對象曹洽,對應(yīng)于NSArraygetObjects:range:方法,transactions數(shù)組的相應(yīng)方法是:

    - (void)getTransactions:(Transaction * __unsafe_unretained *)buffer
                 range:(NSRange)inRange {
                 
      [self.transactions getObjects:buffer range:inRange];
    }
    

比如在一個Person類中辽剧,定義了一個gender屬性(NSString對象)送淆,這里我們在.m文件為其實現(xiàn)相應(yīng)的集合方法,這樣gender就會表現(xiàn)的跟一個數(shù)組一樣怕轿。

@interface Person : NSObject
@property (nonatomic , copy) NSString *gender;
@end

@implementation Person
// 使用@dynamic修飾偷崩,所以編譯器不會為其生成getter和setter
@dynamic gender;

- (NSUInteger)countOfGender
{
    return 5;
}
- (id)objectInGenderAtIndex:(NSUInteger)index
{
    return @"w";
}
@end
 id obj = [person valueForKey:@"gender"];
 NSString *cls = NSStringFromClass([obj class]);
 NSLog(@"gender: %@", obj);
 NSLog(@"className:%@",cls);

打印信息為

gender: (
w,
w,
w,
w,
w
)
className:NSKeyValueArray

可以看出,雖然我們聲明的是NSString,但由于我們實現(xiàn)了屬性相應(yīng)的集合方法撞羽,這里屬性已經(jīng)變成了NSArray類型阐斜。(而且都是不可變數(shù)組,即使我們聲明的是NSMutableArray類型)

有序集合的改變

使用索引方法來實現(xiàn)可變的 to-many 的關(guān)系必須實現(xiàn)一組不同的方法诀紊。當你提供這些setter方法時谒出,mutableArrayValueForKey:消息的默認實現(xiàn)是返回一個與NSMutableArray行為相似的代理對象。這比直接返回一個NSMutableArray對象更加有效率。

為了使鍵值編碼對象表現(xiàn)跟可變笤喳、有序的 to-many 關(guān)系一樣考赛,需要實現(xiàn)以下這些方法:

  • insertObject:in<Key>AtIndex: or insert<Key>:atIndexes:

    第一個方法接收要插入的對象和指定應(yīng)該插入的位置。第二個方法插入一個對象數(shù)組到NSIndexSet指定的索引處的集合中莉测。這跟NSMutableArrayinsertObject:atIndex:insertObjects:atIndexes:方法類似。只需要其中一個方法唧喉。

    - (void)insertObject:(Transaction *)transaction
    inTransactionsAtIndex:(NSUInteger)index {
    [self.transactions insertObject:transaction atIndex:index];
    }
    
    - (void)insertTransactions:(NSArray *)transactionArray
             atIndexes:(NSIndexSet *)indexes {
    [self.transactions insertObjects:transactionArray atIndexes:indexes];
    }
    
  • removeObjectFrom<Key>AtIndex: or remove<Key>AtIndexes:

    第一個接收一個NSUInteger值捣卤,第二個接收一個NSIndexSet對象,指定要刪除的對象的索引八孝。 這些方法分別對應(yīng)于NSMutableArray方法removeObjectAtIndex:removeObjectsAtIndexes:董朝。 只需要其中一種方法。

    - (void)removeObjectFromTransactionsAtIndex:(NSUInteger)index {
     [self.transactions removeObjectAtIndex:index];
    }
    
    - (void)removeTransactionsAtIndexes:(NSIndexSet *)indexes {
     [self.transactions removeObjectsAtIndexes:indexes];
    }
    
  • replaceObjectIn<Key>AtIndex:withObject:replace<Key>AtIndexes:with<Key>:

    為代理對象提供了一種直接替換集合中對象的方法干跛,而無需連續(xù)刪除一個對象并插入另一個對象子姜。對應(yīng)于NSMutableArrayreplaceObjectAtIndex:withObject:replaceObjectsAtIndexes:withObjects:方法。當應(yīng)用程序分析顯示性能問題時楼入,可以選擇提供這些方法哥捕。

    - (void)replaceObjectInTransactionsAtIndex:(NSUInteger)index
                               withObject:(id)anObject {
      [self.transactions replaceObjectAtIndex:index
                                withObject:anObject];
    }
    
     - (void)replaceTransactionsAtIndexes:(NSIndexSet *)indexes
                      withTransactions:(NSArray *)transactionArray {
      [self.transactions replaceObjectsAtIndexes:indexes
                                  withObjects:transactionArray];
    }
    

訪問無序集合

通常,這種關(guān)系是NSSetNSMutableSet對象的一個實例嘉熊。 但是遥赚,實現(xiàn)這些方法時,我們可以使用鍵值編碼對該對象進行操作阐肤,就像它是NSSet的實例一樣凫佛。

無序集合的getter

當你提供以下集合方法以返回集合中對象的數(shù)量的時候,valueForKey:消息返回一個跟NSSet行為類似的代理對象孕惜,但是是調(diào)用下面的集合方法來完成愧薛。

  • countOf<Key>

    該必需方法返回關(guān)系中條目的數(shù)量,對應(yīng)NSSetcount方法衫画。當?shù)讓訉ο笫?code>NSSet對象毫炉,會直接調(diào)用count方法。比如

     - (NSUInteger)countOfEmployees {
       return [self.employees count];
     }
    
  • enumeratorOf<Key>

    這個必需方法返回一個NSEnumerator實例,用于遍歷關(guān)系中的條目削罩。

    - (NSEnumerator *)enumeratorOfEmployees {
     return [self.employees objectEnumerator];
    }
    
  • memberOf<Key>:

    這個方法將作為參數(shù)傳過來的對象和集合中的內(nèi)容進行比較碘箍,并返回匹配的對象,如果沒有找到匹配的對象返回nil鲸郊。如果要手動實現(xiàn)比較方法丰榴,通常是使用isEqual:來比較對象。如果底層對象是NSSet對象秆撮,可以使用member:方法

    - (Employee *)memberOfEmployees:(Employee *)anObject {
    return [self.employees member:anObject];
    }
    

無序集合的改變

為了使可變無序的to-many關(guān)系的支持鍵值編碼四濒,需要實現(xiàn)以下方法:

  • add<Key>Object: or add<Key>:

添加單個或多個對象。當添加多個對象時,請確保關(guān)系中不存在同等的對象盗蟆。這與NSMutableSetaddObject:unionSet:方法類似戈二。 只需要其中一個方法:

 - (void)addEmployeesObject:(Employee *)anObject {
 [self.employees addObject:anObject];
 }

 - (void)addEmployees:(NSSet *)manyObjects {
 [self.employees unionSet:manyObjects];
 }
  • remove<Key>Object: or remove<Key>:

    從關(guān)系中刪除單個或者多個對象。這與NSMutableSetremoveObject:minusSet:類似喳资。 只需要其中一個方法:

    - (void)removeEmployeesObject:(Employee *)anObject {
     [self.employees removeObject:anObject];
    }
    
    - (void)removeEmployees:(NSSet *)manyObjects {
     [self.employees minusSet:manyObjects];
    }
    
  • intersect<Key>:

    這個方法接收一個NSSet作為參數(shù)觉吭,從關(guān)系中刪除不為輸入集與集合中共有的所有對象。這跟NSMutableSetintersectSet:方法等效仆邓。該方法是可選的鲜滩。

    - (void)intersectEmployees:(NSSet *)otherObjects {
      return [self.employees intersectSet:otherObjects];
    }
    
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市节值,隨后出現(xiàn)的幾起案子徙硅,更是在濱河造成了極大的恐慌,老刑警劉巖搞疗,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嗓蘑,死亡現(xiàn)場離奇詭異,居然都是意外死亡匿乃,警方通過查閱死者的電腦和手機桩皿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來幢炸,“玉大人业簿,你說我怎么就攤上這事⊙舳” “怎么了梅尤?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長岩调。 經(jīng)常有香客問我巷燥,道長,這世上最難降的妖魔是什么号枕? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任缰揪,我火速辦了婚禮,結(jié)果婚禮上葱淳,老公的妹妹穿的比我還像新娘钝腺。我一直安慰自己,他們只是感情好赞厕,可當我...
    茶點故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布艳狐。 她就那樣靜靜地躺著,像睡著了一般皿桑。 火紅的嫁衣襯著肌膚如雪毫目。 梳的紋絲不亂的頭發(fā)上蔬啡,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天,我揣著相機與錄音镀虐,去河邊找鬼箱蟆。 笑死,一個胖子當著我的面吹牛刮便,可吹牛的內(nèi)容都是我干的空猜。 我是一名探鬼主播,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼恨旱,長吁一口氣:“原來是場噩夢啊……” “哼辈毯!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起窖杀,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎裙士,沒想到半個月后入客,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡腿椎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年桌硫,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片啃炸。...
    茶點故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡铆隘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出南用,到底是詐尸還是另有隱情膀钠,我是刑警寧澤,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布裹虫,位于F島的核電站肿嘲,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏筑公。R本人自食惡果不足惜雳窟,卻給世界環(huán)境...
    茶點故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望匣屡。 院中可真熱鬧封救,春花似錦、人聲如沸捣作。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽券躁。三九已至搓彻,卻和暖如春如绸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背旭贬。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工怔接, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人稀轨。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓扼脐,卻偏偏與公主長得像,于是被迫代替她去往敵國和親奋刽。 傳聞我的和親對象是個殘疾皇子瓦侮,可洞房花燭夜當晚...
    茶點故事閱讀 45,573評論 2 359

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